File Coverage

lib/App/perlbrew.pm
Criterion Covered Total %
statement 899 1334 67.3
branch 329 634 51.8
condition 102 234 43.5
subroutine 104 136 76.4
pod 0 115 0.0
total 1434 2453 58.4


line stmt bran cond sub pod time code
1             package App::perlbrew;
2 58     58   2435977 use strict;
  58         461  
  58         1413  
3 58     58   285 use warnings;
  58         94  
  58         1160  
4 58     58   1174 use 5.008;
  58         179  
5             our $VERSION = "0.96";
6 58     58   298 use Config;
  58         105  
  58         5682  
7              
8             BEGIN {
9             # Special treat for Cwd to prevent it to be loaded from somewhere binary-incompatible with system perl.
10 58     58   351 my @oldinc = @INC;
11              
12             @INC = (
13             $Config{sitelibexp}."/".$Config{archname},
14             $Config{sitelibexp},
15 58         9133 @Config{qw},
16             );
17              
18 58         432 require Cwd;
19 58         1432 @INC = @oldinc;
20             }
21              
22 58     58   35595 use Getopt::Long ();
  58         587726  
  58         1667  
23 58     58   26164 use CPAN::Perl::Releases;
  58         140558  
  58         3537  
24 58     58   35632 use JSON::PP 'decode_json';
  58         686873  
  58         3769  
25 58     58   24665 use File::Copy 'copy';
  58         112836  
  58         2808  
26 58     58   23260 use Capture::Tiny ();
  58         985623  
  58         1530  
27              
28 58     58   20218 use App::Perlbrew::Util;
  58         162  
  58         3210  
29 58     58   18213 use App::Perlbrew::Path;
  58         144  
  58         1591  
30 58     58   18533 use App::Perlbrew::Path::Root;
  58         150  
  58         1631  
31 58     58   19099 use App::Perlbrew::HTTP qw(http_get http_download);
  58         160  
  58         92141  
32              
33             ### global variables
34              
35             # set $ENV{SHELL} to executable path of parent process (= shell) if it's missing
36             # (e.g. if this script was executed by a daemon started with "service xxx start")
37             # ref: https://github.com/gugod/App-perlbrew/pull/404
38             $ENV{SHELL} ||= App::Perlbrew::Path->new ("/proc", getppid, "exe")->readlink if -d "/proc";
39              
40             local $SIG{__DIE__} = sub {
41             my $message = shift;
42             warn $message;
43             exit(1);
44             };
45              
46             our $CONFIG;
47             our $PERLBREW_ROOT;
48             our $PERLBREW_HOME;
49              
50             my @flavors = ( { d_option => 'usethreads',
51             implies => 'multi',
52             common => 1,
53             opt => 'thread|threads' }, # threads is for backward compatibility
54              
55             { d_option => 'usemultiplicity',
56             opt => 'multi' },
57              
58             { d_option => 'uselongdouble',
59             common => 1,
60             opt => 'ld' },
61              
62             { d_option => 'use64bitint',
63             common => 1,
64             opt => '64int' },
65              
66             { d_option => 'use64bitall',
67             implies => '64int',
68             opt => '64all' },
69              
70             { d_option => 'DEBUGGING',
71             opt => 'debug' },
72              
73             { d_option => 'cc=clang',
74             opt => 'clang' },
75             );
76              
77             my %flavor;
78             my $flavor_ix = 0;
79             for (@flavors) {
80             my ($name) = $_->{opt} =~ /([^|]+)/;
81             $_->{name} = $name;
82             $_->{ix} = ++$flavor_ix;
83             $flavor{$name} = $_;
84             }
85             for (@flavors) {
86             if (my $implies = $_->{implies}) {
87             $flavor{$implies}{implied_by} = $_->{name};
88             }
89             }
90              
91             ### methods
92             sub new {
93 215     215 0 284612 my($class, @argv) = @_;
94              
95 215         3344 my %opt = (
96             original_argv => \@argv,
97             args => [],
98             yes => 0,
99             force => 0,
100             quiet => 0,
101             D => [],
102             U => [],
103             A => [],
104             sitecustomize => '',
105             destdir => '',
106             noman => '',
107             variation => '',
108             both => [],
109             append => '',
110             reverse => 0,
111             verbose => 0,
112             );
113              
114 215         1800 $opt{$_} = '' for keys %flavor;
115              
116 215 100       792 if (@argv) {
117             # build a local @ARGV to allow us to use an older
118             # Getopt::Long API in case we are building on an older system
119 143         688 local (@ARGV) = @argv;
120              
121 143         979 Getopt::Long::Configure(
122             'pass_through',
123             'no_ignore_case',
124             'bundling',
125             'permute', # default behaviour except 'exec'
126             );
127              
128 143         10625 $class->parse_cmdline(\%opt);
129              
130 143         245596 $opt{args} = \@ARGV;
131              
132             # fix up the effect of 'bundling'
133 143         503 foreach my $flags (@opt{qw(D U A)}) {
134 429         521 foreach my $value (@{$flags}) {
  429         718  
135 13         28 $value =~ s/^=//;
136             }
137             }
138             }
139              
140 215         764 my $self = bless \%opt, $class;
141              
142             # Treat --root option same way as env variable PERLBREW_ROOT (with higher priority)
143 215 100       633 if ($opt{root}) {
144 3         10 $ENV{PERLBREW_ROOT} = $self->root($opt{root});
145             }
146              
147 215 100       523 if ($opt{builddir}) {
148 1         8 $self->{builddir} = App::Perlbrew::Path->new($opt{builddir});
149             }
150              
151             # Ensure propagation of $PERLBREW_HOME and $PERLBREW_ROOT
152 215         670 $self->root;
153 215         622 $self->home;
154              
155 215 100       570 if ($self->{verbose}) {
156 3         10 $App::Perlbrew::HTTP::HTTP_VERBOSE = 1;
157             }
158              
159 215         792 return $self;
160             }
161              
162             sub parse_cmdline {
163 177     177 0 474 my ($self, $params, @ext) = @_;
164              
165 177 50       511 my @f = map { $flavor{$_}{opt} || $_ } keys %flavor;
  1239         3569  
166              
167 177         891 return Getopt::Long::GetOptions(
168             $params,
169              
170             'yes',
171             'force|f',
172             'reverse',
173             'notest|n',
174             'quiet|q',
175             'verbose|v',
176             'as=s',
177             'append=s',
178             'help|h',
179             'version',
180             'root=s',
181             'switch',
182             'all',
183             'shell=s',
184             'no-patchperl',
185             'no-decoration',
186              
187             "builddir=s",
188              
189             # options passed directly to Configure
190             'D=s@',
191             'U=s@',
192             'A=s@',
193              
194             'j=i',
195             # options that affect Configure and customize post-build
196             'sitecustomize=s',
197             'destdir=s',
198             'noman',
199              
200             # flavors support
201             'both|b=s@',
202             'all-variations',
203             'common-variations',
204             @f,
205              
206             @ext
207             )
208             }
209              
210             sub root {
211 745     745 0 2050 my ($self, $new_root) = @_;
212              
213             $new_root ||= $PERLBREW_ROOT
214             || $ENV{PERLBREW_ROOT}
215             || App::Perlbrew::Path->new ($ENV{HOME}, "perl5", "perlbrew")->stringify
216 745 100 66     4296 unless $self->{root};
      33        
217              
218 745 100       1783 $self->{root} = $PERLBREW_ROOT = $new_root
219             if defined $new_root;
220              
221             $self->{root} = App::Perlbrew::Path::Root->new ($self->{root})
222 745 100       2823 unless ref $self->{root};
223              
224             $self->{root} = App::Perlbrew::Path::Root->new ($self->{root}->stringify)
225 745 50       2528 unless $self->{root}->isa ('App::Perlbrew::Path::Root');
226              
227 745         1942 return $self->{root};
228             }
229              
230             sub home {
231 790     790 0 1341 my ($self, $new_home) = @_;
232              
233             $new_home ||= $PERLBREW_HOME
234             || $ENV{PERLBREW_HOME}
235             || App::Perlbrew::Path->new ($ENV{HOME}, ".perlbrew")->stringify
236 790 100 66     3801 unless $self->{home};
      33        
237              
238 790 100       1698 $self->{home} = $PERLBREW_HOME = $new_home
239             if defined $new_home;
240              
241             $self->{home} = App::Perlbrew::Path->new ($self->{home})
242 790 100       2066 unless ref $self->{home};
243              
244 790         1937 return $self->{home};
245             }
246              
247             sub builddir {
248 4     4 0 19 my ($self) = @_;
249              
250 4   66     19 return $self->{builddir} || $self->root->build;
251             }
252              
253             sub current_perl {
254 686     686 0 1235 my ($self, $v) = @_;
255 686 100       1082 $self->{current_perl} = $v if $v;
256 686   100     2065 return $self->{current_perl} || $self->env('PERLBREW_PERL') || '';
257             }
258              
259             sub current_lib {
260 502     502 0 1214 my ($self, $v) = @_;
261 502 50       787 $self->{current_lib} = $v if $v;
262 502   100     1349 return $self->{current_lib} || $self->env('PERLBREW_LIB') || '';
263             }
264              
265             sub current_shell_is_bashish {
266 4     4 0 10 my ($self) = @_;
267 4   100     7 return ($self->current_shell eq 'bash') || ($self->current_shell eq 'zsh');
268             }
269              
270             sub current_shell {
271 22     22 0 1320 my ($self, $x) = @_;
272 22 100       49 $self->{current_shell} = $x if $x;
273 22   66     144 return $self->{current_shell} ||= do {
274 2   33     27 my $shell_name = App::Perlbrew::Path->new ($self->{shell} || $self->env('SHELL'))->basename;
275 2         19 $shell_name =~ s/\d+$//;
276 2         25 $shell_name;
277             };
278             }
279              
280             sub current_env {
281 462     462 0 696 my ($self) = @_;
282 462         787 my $l = $self->current_lib;
283 462 100       888 $l = "@" . $l if $l;
284 462         1104 return $self->current_perl . $l;
285             }
286              
287             sub installed_perl_executable {
288 1     1 0 3 my ($self, $name) = @_;
289 1 50       4 die unless $name;
290              
291 1         4 my $executable = $self->root->perls ($name)->perl;
292 1 50       4 return $executable if -e $executable;
293 0         0 return "";
294             }
295              
296             sub configure_args {
297 0     0 0 0 my ($self, $name) = @_;
298              
299 0         0 my $perl_cmd = $self->installed_perl_executable($name);
300 0         0 my $code = 'while(($_,$v)=each(%Config)){print"$_ $v" if /config_arg/}';
301              
302 0         0 my @output = split "\n" => $self->do_capture($perl_cmd, '-MConfig', '-wle', $code);
303              
304 0         0 my %arg;
305 0         0 for(@output) {
306 0         0 my ($k, $v) = split " ", $_, 2;
307 0         0 $arg{$k} = $v;
308             }
309              
310 0 0       0 if (wantarray) {
311 0         0 return map { $arg{"config_arg$_"} } (1 .. $arg{config_argc})
312 0         0 }
313              
314             return $arg{config_args}
315 0         0 }
316              
317             sub cpan_mirror {
318 11     11 0 33 my ($self, $v) = @_;
319              
320 11 100       22 $self->{cpan_mirror} = $v if $v;
321              
322 11 100       27 unless($self->{cpan_mirror}) {
323 5   50     13 $self->{cpan_mirror} = $self->env("PERLBREW_CPAN_MIRROR") || "https://cpan.metacpan.org";
324 5         23 $self->{cpan_mirror} =~ s{/+$}{};
325             }
326              
327 11         21 return $self->{cpan_mirror};
328             }
329              
330             sub env {
331 1265     1265 0 1953 my ($self, $name) = @_;
332 1265 50       6475 return $ENV{$name} if $name;
333 0         0 return \%ENV;
334             }
335              
336             sub is_shell_csh {
337 0     0 0 0 my ($self) = @_;
338 0 0       0 return 1 if $self->env('SHELL') =~ /(t?csh)/;
339 0         0 return 0;
340             }
341              
342             # Entry point method: handles all the arguments
343             # and dispatches to an appropriate internal
344             # method to execute the corresponding command.
345             sub run {
346 138     138 0 51488 my($self) = @_;
347 138         409 $self->run_command($self->args);
348             }
349              
350             sub args {
351 142     142 0 6793 my ($self) = @_;
352              
353             # keep 'force' and 'yes' coherent across commands
354 142 50 33     977 $self->{force} = $self->{yes} = 1 if ($self->{force} || $self->{yes});
355              
356 142         233 return @{ $self->{args} };
  142         634  
357             }
358              
359             sub commands {
360 6     6 0 1128 my ($self) = @_;
361              
362 6 50       19 my $package = ref $self ? ref $self : $self;
363              
364 6         8 my @commands;
365 6         20 my $symtable = do {
366 58     58   492 no strict 'refs';
  58         112  
  58         556530  
367 6         8 \%{$package . '::'};
  6         24  
368             };
369              
370 6         374 foreach my $sym (keys %$symtable) {
371 829 100       1350 if ($sym =~ /^run_command_/) {
372 242         626 my $glob = $symtable->{$sym};
373 242 100 66     685 if (ref($glob) eq 'CODE' || defined *$glob{CODE}) {
374             # with perl >= 5.27 stash entry can points to a CV directly
375 240         500 $sym =~ s/^run_command_//;
376 240         418 $sym =~ s/_/-/g;
377 240         533 push @commands, $sym;
378             }
379             }
380             }
381              
382 6         146 return @commands;
383             }
384              
385             sub find_similar_commands {
386 1     1 0 3 my ($self, $command) = @_;
387 1         3 my $SIMILAR_DISTANCE = 6;
388              
389 1         4 $command =~ s/_/-/g;
390              
391             my @commands = sort {
392 0         0 $a->[1] <=> $b->[1]
393             } map {
394 1         4 my $d = editdist($_, $command);
  40         65  
395 40 50       71 (($d < $SIMILAR_DISTANCE) ? [ $_, $d ] : ())
396             } $self->commands;
397              
398 1 50       10 if (@commands) {
399 0         0 my $best = $commands[0][1];
400 0         0 @commands = map { $_->[0] } grep { $_->[1] == $best } @commands;
  0         0  
  0         0  
401             }
402              
403 1         4 return @commands;
404             }
405              
406             # This method is called in the 'run' loop
407             # and executes every specific action depending
408             # on the type of command.
409             #
410             # The first argument to this method is a self reference,
411             # while the first "real" argument is the command to execute.
412             # Other parameters after the command to execute are
413             # considered as arguments for the command itself.
414             #
415             # In general the command is executed via a method named after the
416             # command itself and with the 'run_command' prefix. For instance
417             # the command 'exec' is handled by a method
418             # `run_command_exec`
419             #
420             # If no candidates can be found, an execption is thrown
421             # and a similar command is shown to the user.
422             sub run_command {
423 138     138 0 355 my ($self, $x, @args) = @_;
424 138         286 my $command = $x;
425              
426 138 50       616 if ($self->{version}) {
    50          
    50          
427 0         0 $x = 'version';
428             }
429             elsif (!$x) {
430 0         0 $x = 'help';
431 0         0 @args = (0, 0);
432             }
433             elsif ($x eq 'help') {
434 0 0       0 @args = (0, 2) unless @args;
435             }
436              
437 138         761 my $s = $self->can("run_command_$x");
438 138 100       382 unless ($s) {
439 18         49 $x =~ y/-/_/;
440 18         77 $s = $self->can("run_command_$x");
441             }
442              
443 138 100       319 unless ($s) {
444 1         5 my @commands = $self->find_similar_commands($x);
445              
446 1 50       7 if (@commands > 1) {
    50          
447 0         0 @commands = map { ' ' . $_ } @commands;
  0         0  
448 0         0 die "Unknown command: `$command`. Did you mean one of the following?\n" . join("\n", @commands) . "\n";
449             } elsif (@commands == 1) {
450 0         0 die "Unknown command: `$command`. Did you mean `$commands[0]`?\n";
451             } else {
452 1         52 die "Unknown command: `$command`. Typo?\n";
453             }
454             }
455              
456 137         425 $self->$s(@args);
457             }
458              
459             sub run_command_version {
460 1     1 0 11 my ($self) = @_;
461 1         2 my $package = ref $self;
462 1         17 my $version = $self->VERSION;
463 1         50 print "$0 - $package/$version\n";
464             }
465              
466             # Provides help information about a command.
467             # The idea is similar to the 'run_command' and 'run_command_$x' chain:
468             # this method dispatches to a 'run_command_help_$x' method
469             # if found in the class, otherwise it tries to extract the help
470             # documentation via the POD of the class itself using the
471             # section 'COMMAND: $x' with uppercase $x.
472             sub run_command_help {
473 2     2 0 20 my ($self, $status, $verbose, $return_text) = @_;
474              
475 2         770 require Pod::Usage;
476              
477 2 50 33     46309 if ($status && !defined($verbose)) {
478 2 50       57 if ($self->can("run_command_help_${status}")) {
479 0         0 $self->can("run_command_help_${status}")->($self);
480             }
481             else {
482 2         6 my $out = "";
483 2         48 open my $fh, ">", \$out;
484              
485 2         17 Pod::Usage::pod2usage(
486             -exitval => "NOEXIT",
487             -verbose => 99,
488             -sections => "COMMAND: " . uc($status),
489             -output => $fh,
490             -noperldoc => 1
491             );
492 2         8458 $out =~ s/\A[^\n]+\n//s;
493 2         5 $out =~ s/^ //gm;
494              
495 2 50       24 if ($out =~ /\A\s*\Z/) {
496 2         7 $out = "Cannot find documentation for '$status'\n\n";
497             }
498              
499 2 50       52 return "\n$out" if ($return_text);
500 0         0 print "\n$out";
501 0         0 close $fh;
502             }
503             }
504             else {
505 0 0 0     0 Pod::Usage::pod2usage(
506             -noperldoc => 1,
507             -verbose => $verbose||0,
508             -exitval => (defined $status ? $status : 1)
509             );
510             }
511             }
512              
513             # introspection for compgen
514             my %comp_installed = (
515             use => 1,
516             switch => 1,
517             );
518              
519             sub run_command_compgen {
520 7     7 0 25 my($self, $cur, @args) = @_;
521              
522 7 100       20 $cur = 0 unless defined($cur);
523              
524             # do `tail -f bashcomp.log` for debugging
525 7 50       25 if ($self->env('PERLBREW_DEBUG_COMPLETION')) {
526 0         0 open my $log, '>>', 'bashcomp.log';
527 0         0 print $log "[$$] $cur of [@args]\n";
528             }
529 7         16 my $subcommand = $args[1];
530 7         12 my $subcommand_completed = ($cur >= 2);
531              
532 7 100       25 if (!$subcommand_completed) {
533 3         10 $self->_compgen($subcommand, $self->commands);
534             }
535             else { # complete args of a subcommand
536 4 50       12 if ($comp_installed{$subcommand}) {
    0          
537 4 50       19 if ($cur <= 2) {
538 4         7 my $part;
539 4 100       11 if (defined($part = $args[2])) {
540 2         40 $part = qr/ \Q$part\E /xms;
541             }
542             $self->_compgen($part,
543 4         24 map{ $_->{name} } $self->installed_perls());
  16         67  
544             }
545             }
546             elsif ($subcommand eq 'help') {
547 0 0       0 if ($cur <= 2) {
548 0         0 $self->_compgen($args[2], $self->commands());
549             }
550             }
551             else {
552             # TODO
553             }
554             }
555             }
556              
557             sub _firstrcfile {
558 4     4   41 my ($self, @files) = @_;
559 4         51 foreach my $path (@files) {
560 13 100       52 return $path if -f App::Perlbrew::Path->new ($self->env('HOME'), $path);
561             }
562 0         0 return;
563             }
564              
565             sub _compgen {
566 7     7   35 my($self, $part, @reply) = @_;
567 7 100       18 if (defined $part) {
568 4 100       80 $part = qr/\A \Q$part\E /xms if ref($part) ne ref(qr//);
569 4         18 @reply = grep { /$part/ } @reply;
  88         175  
570             }
571 7         24 foreach my $word(@reply) {
572 59         909 print $word, "\n";
573             }
574             }
575              
576             # Internal utility function.
577             # Given a specific perl version, e.g., perl-5.27.4
578             # returns a string with a formatted version number such
579             # as 05027004. Such string can be used as a number
580             # in order to make either a string comparison
581             # or a numeric comparison.
582             #
583             # In the case of cperl the major number is added by 6
584             # so that it would match the project claim of being
585             # Perl 5+6 = 11. The final result is then
586             # multiplied by a negative factor (-1) in order
587             # to make cperl being "less" in the ordered list
588             # than a normal Perl installation.
589             #
590             # The returned string is made by four pieces of two digits each:
591             # MMmmppbb
592             # where:
593             # MM is the major Perl version (e.g., 5 -> 05)
594             # mm is the minor Perl version (e.g. 27 -> 27)
595             # pp is the patch level (e.g., 4 -> 04)
596             # bb is the blead flag: it is 00 for a "normal" release, or 01 for a blead one
597             sub comparable_perl_version {
598 628     628 0 85043 my ($self, $perl_version) = @_;
599 628         1056 my ($is_cperl, $is_blead) = (0, 0);
600 628         986 my ($major, $minor, $patch) = (0, 0, 0);
601 628 50       4318 if ($perl_version =~ /^(?:(c?perl)-?)?(\d)\.(\d+).(\d+).*/) {
    0          
602 628   100     2095 $is_cperl = $1 && ($1 eq 'cperl');
603 628 100       1776 $major = $2 + ($is_cperl ? 6 : 0); # major version
604 628         986 $minor = $3; # minor version
605 628         1138 $patch = $4; # patch level
606              
607             }
608             elsif ($perl_version =~ /^(?:(c?perl)-?)?-?(blead)$/) {
609             # in the case of a blead release use a fake high number
610             # to assume it is the "latest" release number available
611 0   0     0 $is_cperl = $1 && ($1 eq 'cperl');
612 0   0     0 $is_blead = $2 && ($2 eq 'blead');
613 0         0 ($major, $minor, $patch) = (5, 99, 99);
614             }
615              
616 628 100       7594 return ($is_cperl ? -1 : 1)
    100          
617             * sprintf('%02d%02d%02d%02d',
618             $major + ($is_cperl ? 6 : 0), # major version
619             $minor, # minor version
620             $patch, # patch level
621             $is_blead); # blead
622             }
623              
624             # Internal method.
625             # Performs a comparable sort of the perl versions specified as
626             # list.
627             sub sort_perl_versions {
628 6     6 0 69 my ($self, @perls) = @_;
629              
630 48         73 return map { $_->[ 0 ] }
631             sort { ( $self->{reverse}
632 106 50       152 ? $a->[ 1 ] <=> $b->[ 1 ]
633             : $b->[ 1 ] <=> $a->[ 1 ] ) }
634 6         17 map { [ $_, $self->comparable_perl_version($_) ] }
  48         94  
635             @perls;
636             }
637              
638             sub run_command_available {
639 3     3 0 6 my ($self) = @_;
640              
641 3         13 my @installed = $self->installed_perls(@_);
642 3         56 my $is_verbose = $self->{verbose};
643              
644 3         12 my @sections = (
645             [ 'perl', 'available_perl_distributions'],
646             [ 'cperl', 'available_cperl_distributions'],
647             );
648              
649 3         15 for (@sections) {
650 5         11 my ($header, $method) = @$_;
651              
652 5         473 print "# $header\n";
653              
654 5         32 my $perls = $self->$method;
655             # sort the keys of Perl installation (Randal to the rescue!)
656 4         172 my @sorted_perls = $self->sort_perl_versions(keys %$perls);
657              
658 4         13 for my $available (@sorted_perls) {
659 32         79 my $url = $perls->{$available};
660 32         32 my $ctime;
661              
662 32         41 for my $installed (@installed) {
663 32         37 my $name = $installed->{name};
664 32         30 my $cur = $installed->{is_current};
665 32 100       56 if ($available eq $installed->{name}) {
666 1         3 $ctime = $installed->{ctime};
667 1         3 last;
668             }
669             }
670              
671 32 50       419 printf "%1s %12s %s %s\n",
    50          
    50          
    50          
672             $ctime ? 'i' : '',
673             $available,
674             ( $is_verbose
675             ? $ctime ? "INSTALLED on $ctime via" : 'available from '
676             : ''),
677             ( $is_verbose ? "<$url>" : '' ) ;
678             }
679 4         43 print "\n\n";
680             }
681              
682 2         14 return;
683             }
684              
685             sub available_perls {
686 0     0 0 0 my ($self) = @_;
687             my %dists = (
688 0         0 %{ $self->available_perl_distributions },
689 0         0 %{ $self->available_cperl_distributions },
  0         0  
690             );
691 0         0 return $self->sort_perl_versions(keys %dists);
692             }
693              
694             # -> Map[ NameVersion => URL ]
695             sub available_perl_distributions {
696 3     3 0 10 my ($self) = @_;
697 3         6 my $perls = {};
698 3         3 my @perllist;
699              
700             # we got impatient waiting for cpan.org to get updated to show 5.28...
701             # So, we also fetch from metacpan for anything that looks perlish,
702             # and we do our own processing to filter out the development
703             # releases and minor versions when needed (using
704             # filter_perl_available)
705 3         5 my $url = 'https://fastapi.metacpan.org/v1/release/versions/perl';
706 3         8 my $json = http_get($url, undef, undef);
707 3 100       25 unless ($json) {
708 2         28 die "\nERROR: Unable to retrieve list of perls from Metacpan.\n\n";
709             }
710              
711 1         4 my $decoded = decode_json($json);
712 1         498032 for my $release (@{ $decoded->{releases} }) {
  1         5  
713 250         534 push @perllist, [ $release->{name}, $release->{download_url} ];
714             }
715 1         7 foreach my $perl ($self->filter_perl_available(\@perllist)) {
716 11         22 $perls->{ $perl->[0] } = $perl->[1];
717             }
718              
719 1         132 return $perls;
720             }
721              
722             # -> Map[ NameVersion => URL ]
723             sub available_cperl_distributions {
724 1     1 0 5 my ($self) = @_;
725 1         2 my %dist;
726              
727             # cperl releases: https://github.com/perl11/cperl/tags
728 1         2 my $cperl_remote = 'https://github.com';
729 1         2 my $url_cperl_release_list = $cperl_remote . '/perl11/cperl/releases';
730              
731 1         3 my $html = http_get($url_cperl_release_list);
732              
733 1 50       5 unless ($html) {
734 1         10 die "\nERROR: Unable to retrieve the list of cperl releases from ${url_cperl_release_list}\n";
735             }
736              
737 0 0       0 if ($html) {
738 0         0 while ($html =~ m{href="(/perl11/cperl/releases/download/cperl-(5.+?)/cperl-.+?\.tar\.gz)"}g) {
739 0         0 $dist{ "cperl-$2" } = $cperl_remote . $1;
740             }
741             }
742              
743 0         0 return \%dist;
744             }
745              
746             # $perllist is an arrayref of arrayrefs. The inner arrayrefs are of the
747             # format: [ , ]
748             # perl_name = something like perl-5.28.0
749             # perl_url = URL the Perl is available from.
750             #
751             # If $self->{all} is true, this just returns a list of the contents of
752             # the list referenced by $perllist
753             #
754             # Otherwise, this looks for even middle numbers in the version and no
755             # suffix (like -RC1) following the URL, and returns the list of
756             # arrayrefs that so match
757             #
758             # If any "newest" Perl has a
759             sub filter_perl_available {
760 1     1 0 4 my ($self, $perllist) = @_;
761              
762 1 50       4 if ($self->{all}) { return @$perllist; }
  0         0  
763              
764 1         2 my %max_release;
765 1         3 foreach my $perl (@$perllist) {
766 250         258 my $ver = $perl->[0];
767 250 100       427 if ($ver !~ m/^perl-5\.[0-9]*[02468]\.[0-9]+$/) { next; } # most likely TRIAL or RC, or a DEV release
  204         239  
768              
769 46         103 my ($release_line, $minor) = $ver =~ m/^perl-5\.([0-9]+)\.([0-9]+)/;
770 46 100       78 if (exists $max_release{$release_line}) {
771 35 50       49 if ($max_release{$release_line}->[0] > $minor) { next; } # We have a newer release
  35         46  
772             }
773              
774 11         38 $max_release{$release_line} = [ $minor, $perl ];
775             }
776              
777 1         4 return map { $_->[1] } values %max_release;
  11         20  
778             }
779              
780             sub perl_release {
781 5     5 0 3122 my ($self, $version) = @_;
782 5         11 my $mirror = $self->cpan_mirror();
783              
784             # try CPAN::Perl::Releases
785 5         21 my $tarballs = CPAN::Perl::Releases::perl_tarballs($version);
786              
787 5         254 my $x = (values %$tarballs)[0];
788 5 100       12 if ($x) {
789 4         10 my $dist_tarball = (split("/", $x))[-1];
790 4         10 my $dist_tarball_url = "$mirror/authors/id/$x";
791 4         15 return ($dist_tarball, $dist_tarball_url);
792             }
793              
794             # try src/5.0 symlinks, either perl-5.X or perl5.X; favor .tar.bz2 over .tar.gz
795 1         3 my $index = http_get("https://cpan.metacpan.org/src/5.0/");
796 1 50       343 if ($index) {
797 1         4 for my $prefix ("perl-", "perl") {
798 2         3 for my $suffix (".tar.bz2", ".tar.gz") {
799 4         9 my $dist_tarball = "$prefix$version$suffix";
800 4         6 my $dist_tarball_url = "$mirror/src/5.0/$dist_tarball";
801 4 50       53 return ($dist_tarball, $dist_tarball_url)
802             if ($index =~ /href\s*=\s*"\Q$dist_tarball\E"/ms);
803             }
804             }
805             }
806              
807 1         6 my $json = http_get("'https://fastapi.metacpan.org/v1/release/_search?size=1&q=name:perl-${version}'");
808              
809 1         511 my $result;
810 1 50 33     5 unless ($json and $result = decode_json($json)->{hits}{hits}[0]) {
811 0         0 die "ERROR: Failed to locate perl-${version} tarball.";
812             }
813              
814             my ($dist_path, $dist_tarball) =
815 1         987 $result->{_source}{download_url} =~ m[(/authors/id/.+/(perl-${version}.tar.(gz|bz2|xz)))$];
816 1 0 33     6 die "ERROR: Cannot find the tarball for perl-$version\n"
817             if !$dist_path and !$dist_tarball;
818 1         3 my $dist_tarball_url = "https://cpan.metacpan.org${dist_path}";
819 1         5 return ($dist_tarball, $dist_tarball_url);
820             }
821              
822             sub cperl_release {
823 0     0 0 0 my ($self, $version) = @_;
824 0         0 my %url = (
825             "5.22.3" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.3/cperl-5.22.3.tar.gz",
826             "5.22.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.2/cperl-5.22.2.tar.gz",
827             "5.24.0-RC1" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.0-RC1/cperl-5.24.0-RC1.tar.gz",
828             );
829             # my %digest => {
830             # "5.22.3" => "bcf494a6b12643fa5e803f8e0d9cef26312b88fc",
831             # "5.22.2" => "8615964b0a519cf70d69a155b497de98e6a500d0",
832             # };
833              
834 0 0       0 my $dist_tarball_url = $url{$version}or die "ERROR: Cannot find the tarball for cperl-$version\n";
835 0         0 my $dist_tarball = "cperl-${version}.tar.gz";
836 0         0 return ($dist_tarball, $dist_tarball_url);
837             }
838              
839             sub release_detail_perl_local {
840 5     5 0 22 my ($self, $dist, $rd) = @_;
841 5   50     15 $rd ||= {};
842 5         9 my $error = 1;
843 5         23 my $mirror = $self->cpan_mirror();
844 5         27 my $tarballs = CPAN::Perl::Releases::perl_tarballs($rd->{version});
845 5 50       296 if (keys %$tarballs) {
846 5         14 for ("tar.bz2", "tar.gz") {
847 5 50       22 if (my $x = $tarballs->{$_}) {
848 5         29 $rd->{tarball_name} = (split("/", $x))[-1];
849 5         19 $rd->{tarball_url} = "$mirror/authors/id/$x";
850 5         7 $error = 0;
851 5         10 last;
852             }
853             }
854             }
855 5         18 return ($error, $rd);
856             }
857              
858             sub release_detail_perl_remote {
859 0     0 0 0 my ($self, $dist, $rd) = @_;
860 0   0     0 $rd ||= {};
861 0         0 my $error = 1;
862 0         0 my $mirror = $self->cpan_mirror();
863              
864 0         0 my $version = $rd->{version};
865              
866             # try src/5.0 symlinks, either perl-5.X or perl5.X; favor .tar.bz2 over .tar.gz
867 0         0 my $index = http_get("https://cpan.metacpan.org/src/5.0/");
868 0 0       0 if ($index) {
869 0         0 for my $prefix ("perl-", "perl") {
870 0         0 for my $suffix (".tar.bz2", ".tar.gz") {
871 0         0 my $dist_tarball = "$prefix$version$suffix";
872 0         0 my $dist_tarball_url = "$mirror/src/5.0/$dist_tarball";
873 0 0       0 if ($index =~ /href\s*=\s*"\Q$dist_tarball\E"/ms) {
874 0         0 $rd->{tarball_url} = $dist_tarball_url;
875 0         0 $rd->{tarball_name} = $dist_tarball;
876 0         0 $error = 0;
877 0         0 return ($error, $rd);
878             }
879             }
880             }
881             }
882              
883 0         0 my $json = http_get("'https://fastapi.metacpan.org/v1/release/_search?size=1&q=name:perl-${version}'");
884              
885 0         0 my $result;
886 0 0 0     0 unless ($json and $result = decode_json($json)->{hits}{hits}[0]) {
887 0         0 die "ERROR: Failed to locate perl-${version} tarball.";
888             }
889              
890             my ($dist_path, $dist_tarball) =
891 0         0 $result->{_source}{download_url} =~ m[(/authors/id/.+/(perl-${version}.tar.(gz|bz2|xz)))$];
892 0 0 0     0 die "ERROR: Cannot find the tarball for perl-$version\n"
893             if !$dist_path and !$dist_tarball;
894 0         0 my $dist_tarball_url = "https://cpan.metacpan.org${dist_path}";
895              
896 0         0 $rd->{tarball_name} = $dist_tarball;
897 0         0 $rd->{tarball_url} = $dist_tarball_url;
898 0         0 $error = 0;
899              
900 0         0 return ($error, $rd);
901             }
902              
903             sub release_detail_cperl_local {
904 2     2 0 11 my ($self, $dist, $rd) = @_;
905 2   50     5 $rd ||= {};
906 2         20 my %url = (
907             "cperl-5.22.3" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.3/cperl-5.22.3.tar.gz",
908             "cperl-5.22.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.2/cperl-5.22.2.tar.gz",
909             "cperl-5.24.0-RC1" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.0-RC1/cperl-5.24.0-RC1.tar.gz",
910             "cperl-5.24.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.2/cperl-5.24.2.tar.gz",
911             "cperl-5.25.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.2/cperl-5.25.2.tar.gz",
912             "cperl-5.26.4" => "https://github.com/perl11/cperl/releases/download/cperl-5.26.4/cperl-5.26.4.tar.gz",
913             "cperl-5.26.5" => "https://github.com/perl11/cperl/releases/download/cperl-5.26.5/cperl-5.26.5.tar.gz",
914             "cperl-5.28.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.28.2/cperl-5.28.2.tar.gz",
915             "cperl-5.29.0" => "https://github.com/perl11/cperl/releases/download/cperl-5.29.0/cperl-5.29.0.tar.gz",
916             "cperl-5.29.1" => "https://github.com/perl11/cperl/releases/download/cperl-5.29.1/cperl-5.29.1.tar.gz",
917             "cperl-5.30.0" => "https://github.com/perl11/cperl/releases/download/cperl-5.30.0/cperl-5.30.0.tar.gz",
918             );
919              
920 2         4 my $error = 1;
921 2 50       7 if (my $u = $url{$dist}) {
922 2         6 $rd->{tarball_name} = "${dist}.tar.gz";
923 2         5 $rd->{tarball_url} = $u;
924 2         3 $error = 0;
925             }
926 2         7 return ($error, $rd);
927             }
928              
929             sub release_detail_cperl_remote {
930 0     0 0 0 my ($self, $dist, $rd) = @_;
931 0   0     0 $rd ||= {};
932              
933 0         0 my $expect_href = "/perl11/cperl/releases/download/${dist}/${dist}.tar.gz";
934 0         0 my $error = 1;
935              
936 0   0     0 my $html = eval {
937             http_get('https://github.com/perl11/cperl/releases/tag/' . $dist);
938             } || "";
939              
940 0 0       0 if ($html =~ m{
941 0         0 $rd->{tarball_name} = "${dist}.tar.gz";
942 0         0 $rd->{tarball_url} = "https://github.com" . $1;
943 0         0 $error = 0;
944             }
945              
946 0         0 return ($error, $rd);
947             }
948              
949             sub release_detail {
950 5     5 0 24 my ($self, $dist) = @_;
951 5         9 my ($dist_type, $dist_version);
952              
953 5         51 ($dist_type, $dist_version) = $dist =~ /^ (?: (c?perl) -? )? ( [\d._]+ (?:-RC\d+)? |git|stable|blead)$/x;
954 5 100 66     21 $dist_type = "perl" if $dist_version && !$dist_type;
955              
956 5         21 my $rd = {
957             type => $dist_type,
958             version => $dist_version,
959             tarball_url => undef,
960             tarball_name => undef,
961             };
962              
963             # dynamic methods: release_detail_perl_local, release_detail_cperl_local, release_detail_perl_remote, release_detail_cperl_remote
964 5         14 my $m_local = "release_detail_${dist_type}_local";
965 5         18 my $m_remote = "release_detail_${dist_type}_remote";
966              
967 5         21 my ($error) = $self->$m_local($dist, $rd);
968 5 50       14 ($error) = $self->$m_remote($dist, $rd) if $error;
969              
970 5 50       14 if ($error) {
971 0         0 die "ERROR: Fail to get the tarball URL for dist: $dist\n";
972             }
973              
974 5         11 return $rd;
975             }
976              
977             sub run_command_init {
978 5     5 0 20 my $self = shift;
979 5         15 my @args = @_;
980              
981 5 50 33     33 if (@args && $args[0] eq '-') {
982 0 0       0 if ($self->current_shell_is_bashish) {
983 0         0 $self->run_command_init_in_bash;
984             }
985 0         0 exit 0;
986             }
987              
988 5         43 $_->mkpath for (grep { ! -d $_ } map { $self->root->$_ } qw(perls dists build etc bin));
  25         120  
  25         129  
989              
990 5         42 my ($f, $fh) = @_;
991              
992 5         24 my $etc_dir = $self->root->etc;
993              
994 5         158 for (["bashrc", "BASHRC_CONTENT"],
995             ["cshrc", "CSHRC_CONTENT"],
996             ["csh_reinit", "CSH_REINIT_CONTENT"],
997             ["csh_wrapper", "CSH_WRAPPER_CONTENT"],
998             ["csh_set_path", "CSH_SET_PATH_CONTENT"],
999             ["perlbrew-completion.bash", "BASH_COMPLETION_CONTENT"],
1000             ["perlbrew.fish", "PERLBREW_FISH_CONTENT" ],
1001             ) {
1002 35         198 my ($file_name, $method) = @$_;
1003 35         174 my $path = $etc_dir->child ($file_name);
1004 35 100       148 if (! -f $path) {
1005 7 50       51 open($fh, ">", $path) or die "Fail to create $path. Please check the permission of $etc_dir and try `perlbrew init` again.";
1006 7         118 print $fh $self->$method;
1007 7         273 close $fh;
1008             }
1009             else {
1010 28 50 33     163 if (-w $path && open($fh, ">", $path)) {
1011 28         379 print $fh $self->$method;
1012 28         2436 close $fh;
1013             }
1014             else {
1015 0 0       0 print "NOTICE: $path already exists and not updated.\n" unless $self->{quiet};
1016             }
1017             }
1018             }
1019              
1020 5         52 my $root_dir = $self->root->stringify_with_tilde;
1021             # Skip this if we are running in a shell that already 'source's perlbrew.
1022             # This is true during a self-install/self-init.
1023             # Ref. https://github.com/gugod/App-perlbrew/issues/525
1024 5 50       27 if ($ENV{PERLBREW_SHELLRC_VERSION}) {
1025 0         0 print("\nperlbrew root ($root_dir) is initialized.\n");
1026             } else {
1027 5         26 my $shell = $self->current_shell;
1028 5         12 my ($code, $yourshrc);
1029 5 50       135 if ($shell =~ m/(t?csh)/) {
    100          
    100          
1030 0         0 $code = "source $root_dir/etc/cshrc";
1031 0         0 $yourshrc = $1 . "rc";
1032             }
1033             elsif ($shell =~ m/zsh\d?$/) {
1034 1         31 $code = "source $root_dir/etc/bashrc";
1035 1   50     20 $yourshrc = $self->_firstrcfile(qw(
1036             .zshenv
1037             .bash_profile
1038             .bash_login
1039             .profile
1040             )) || ".zshenv";
1041             }
1042             elsif ($shell =~ m/fish/) {
1043 1         28 $code = ". $root_dir/etc/perlbrew.fish";
1044 1         11 $yourshrc = '.config/fish/config.fish';
1045             }
1046             else {
1047 3         27 $code = "source $root_dir/etc/bashrc";
1048 3   50     40 $yourshrc = $self->_firstrcfile(qw(
1049             .bash_profile
1050             .bash_login
1051             .profile
1052             )) || ".bash_profile";
1053             }
1054              
1055 5 100       23 if ($self->home ne App::Perlbrew::Path->new ($self->env('HOME'), ".perlbrew")) {
1056 4         12 my $pb_home_dir = $self->home->stringify_with_tilde;
1057 4 100       30 if ( $shell =~ m/fish/ ) {
1058 1         15 $code = "set -x PERLBREW_HOME $pb_home_dir\n $code";
1059             } else {
1060 3         18 $code = "export PERLBREW_HOME=$pb_home_dir\n $code";
1061             }
1062             }
1063              
1064 5         813 print <
1065              
1066             perlbrew root ($root_dir) is initialized.
1067              
1068             Append the following piece of code to the end of your ~/${yourshrc} and start a
1069             new shell, perlbrew should be up and fully functional from there:
1070              
1071             $code
1072              
1073             Simply run `perlbrew` for usage details.
1074              
1075             Happy brewing!
1076              
1077             INSTRUCTION
1078             }
1079              
1080             }
1081              
1082             sub run_command_init_in_bash {
1083 0     0 0 0 print BASHRC_CONTENT();
1084             }
1085              
1086             sub run_command_self_install {
1087 5     5 0 9 my $self = shift;
1088              
1089 5         10 my $executable = $0;
1090 5         12 my $target = $self->root->bin ("perlbrew");
1091              
1092 5 50       48 if (files_are_the_same($executable, $target)) {
1093 0         0 print "You are already running the installed perlbrew:\n\n $executable\n";
1094 0         0 exit;
1095             }
1096              
1097 5         14 $self->root->bin->mkpath;
1098              
1099 5         159 open my $fh, "<", $executable;
1100              
1101 5         13 my $head;
1102 5         110 read($fh, $head, 3, 0);
1103              
1104 5 50       20 if ($head eq "#!/") {
1105 5         47 seek($fh, 0, 0);
1106 5         209 my @lines = <$fh>;
1107 5         52 close $fh;
1108              
1109 5         23 $lines[0] = $self->system_perl_shebang . "\n";
1110              
1111 5         328 open $fh, ">", $target;
1112 5         430 print $fh $_ for @lines;
1113 5         687 close $fh;
1114             } else {
1115 0         0 close($fh);
1116              
1117 0         0 copy($executable, $target);
1118             }
1119              
1120 5         68 chmod(0755, $target);
1121              
1122 5         59 my $path = $target->stringify_with_tilde;
1123              
1124 5 100       282 print "perlbrew is installed: $path\n" unless $self->{quiet};
1125              
1126 5         61 $self->run_command_init();
1127 5         510 return;
1128             }
1129              
1130             sub do_install_git {
1131 0     0 0 0 my ($self, $dist) = @_;
1132 0         0 my $dist_name;
1133             my $dist_git_describe;
1134 0         0 my $dist_version;
1135              
1136 0         0 opendir my $cwd_orig, ".";
1137              
1138 0         0 chdir $dist;
1139              
1140 0 0       0 if (`git describe` =~ /v((5\.\d+\.\d+(?:-RC\d)?)(-\d+-\w+)?)$/) {
1141 0         0 $dist_name = 'perl';
1142 0         0 $dist_git_describe = "v$1";
1143 0         0 $dist_version = $2;
1144             }
1145              
1146 0         0 chdir $cwd_orig;
1147              
1148 0         0 require File::Spec;
1149 0         0 my $dist_extracted_dir = File::Spec->rel2abs($dist);
1150 0         0 $self->do_install_this(App::Perlbrew::Path->new ($dist_extracted_dir), $dist_version, "$dist_name-$dist_version");
1151 0         0 return;
1152             }
1153              
1154             sub do_install_url {
1155 3     3 0 564 my ($self, $dist) = @_;
1156 3         13 my $dist_name = 'perl';
1157             # need the period to account for the file extension
1158 3         15 my ($dist_version) = $dist =~ m/-([\d.]+(?:-RC\d+)?|git)\./;
1159 3         19 my ($dist_tarball) = $dist =~ m{/([^/]*)$};
1160              
1161 3 100 66     25 if (! $dist_version && $dist =~ /blead\.tar.gz$/) {
1162 2         4 $dist_version = "blead";
1163             }
1164              
1165 3         8 my $dist_tarball_path = $self->root->dists($dist_tarball);
1166 3         7 my $dist_tarball_url = $dist;
1167 3         9 $dist = "$dist_name-$dist_version"; # we install it as this name later
1168              
1169 3 50       14 if ($dist_tarball_url =~ m/^file/) {
1170 0         0 print "Installing $dist from local archive $dist_tarball_url\n";
1171 0         0 $dist_tarball_url =~ s/^file:\/+/\//;
1172 0         0 $dist_tarball_path = $dist_tarball_url;
1173             }
1174             else {
1175 3         11 print "Fetching $dist as $dist_tarball_path\n";
1176 3         22 my $error = http_download($dist_tarball_url, $dist_tarball_path);
1177 3 100       88 die "ERROR: Failed to download $dist_tarball_url\n$error\n" if $error;
1178             }
1179              
1180 1         3 my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path);
1181 1         44 $self->do_install_this($dist_extracted_path, $dist_version, $dist);
1182 1         29 return;
1183             }
1184              
1185             sub do_extract_tarball {
1186 1     1 0 4 my ($self, $dist_tarball) = @_;
1187              
1188             # Assuming the dir extracted from the tarball is named after the tarball.
1189 1         8 my $dist_tarball_basename = $dist_tarball->basename (qr/\.tar\.(?:gz|bz2|xz)$/);
1190              
1191 1         6 my $workdir;
1192 1 50       5 if ( $self->{as} ) {
1193             # TODO: Should we instead use the installation_name (see run_command_install()):
1194             # $destdir = $self->{as} . $self->{variation} . $self->{append};
1195 0         0 $workdir = $self->builddir->child ($self->{as});
1196             }
1197             else {
1198             # Note that this is incorrect for blead.
1199 1         5 $workdir = $self->builddir->child ($dist_tarball_basename);
1200             }
1201 1         6 $workdir->rmpath;
1202 1         4 $workdir->mkpath;
1203 1         1 my $extracted_dir;
1204              
1205             # Was broken on Solaris, where GNU tar is probably
1206             # installed as 'gtar' - RT #61042
1207 1 50       11 my $tarx =
    50          
    50          
1208             ($^O =~ /solaris|aix/ ? 'gtar ' : 'tar ') .
1209             ( $dist_tarball =~ m/xz$/ ? 'xJf' :
1210             $dist_tarball =~ m/bz2$/ ? 'xjf' : 'xzf' );
1211              
1212 1         4 my $extract_command = "cd $workdir; $tarx $dist_tarball";
1213 1 50       7370 die "Failed to extract $dist_tarball" if system($extract_command);
1214              
1215 1         68 my @things = $workdir->children;
1216 1 50       7 if (@things == 1) {
1217 1         11 $extracted_dir = App::Perlbrew::Path->new ($things[0]);
1218             }
1219              
1220 1 50 33     19 unless (defined($extracted_dir) && -d $extracted_dir) {
1221 0         0 die "Failed to find the extracted directory under $workdir";
1222             }
1223              
1224 1         21 return $extracted_dir;
1225             }
1226              
1227             sub do_install_blead {
1228 2     2 0 5 my ($self) = @_;
1229              
1230             # We always blindly overwrite anything that's already there,
1231             # because blead is a moving target.
1232 2         5 my $dist_tarball_path = $self->root->dists("blead.tar.gz");
1233 2 50       6 unlink($dist_tarball_path) if -f $dist_tarball_path;
1234              
1235 2         8 $self->do_install_url("https://github.com/Perl/perl5/archive/blead.tar.gz");
1236             }
1237              
1238             sub resolve_stable_version {
1239 2     2 0 4 my ($self) = @_;
1240              
1241 2         5 my ($latest_ver, $latest_minor);
1242 2         8 for my $cand ($self->available_perls) {
1243 11 100       58 my ($ver, $minor) = $cand =~ m/^perl-(5\.(6|8|[0-9]+[02468])\.[0-9]+)$/
1244             or next;
1245 9 100 100     36 ($latest_ver, $latest_minor) = ($ver, $minor)
1246             if !defined $latest_minor
1247             || $latest_minor < $minor;
1248             }
1249              
1250 2 50       7 die "Can't determine latest stable Perl release\n"
1251             if !defined $latest_ver;
1252              
1253 2         5 return $latest_ver;
1254             }
1255              
1256             sub do_install_release {
1257 1     1 0 3 my ($self, $dist, $dist_version) = @_;
1258              
1259 1         2 my $rd = $self->release_detail($dist);
1260 1         2 my $dist_type = $rd->{type};
1261              
1262 1 50 33     8 die "\"$dist\" does not look like a perl distribution name. " unless $dist_type && $dist_version =~ /^\d\./;
1263              
1264 1         2 my $dist_tarball = $rd->{tarball_name};
1265 1         2 my $dist_tarball_url = $rd->{tarball_url};
1266 1         2 my $dist_tarball_path = $self->root->dists ($dist_tarball);
1267              
1268 1 50       3 if (-f $dist_tarball_path) {
1269             print "Using the previously fetched ${dist_tarball}\n"
1270 0 0       0 if $self->{verbose};
1271             }
1272             else {
1273 1 50       7 print "Fetching perl $dist_version as $dist_tarball_path\n" unless $self->{quiet};
1274 1         7 $self->run_command_download($dist);
1275             }
1276              
1277 0         0 my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path);
1278 0         0 $self->do_install_this($dist_extracted_path, $dist_version, $dist);
1279 0         0 return;
1280             }
1281              
1282             sub run_command_install {
1283 62     62 0 165 my ($self, $dist, $opts) = @_;
1284              
1285 62 100       135 unless ($self->root->exists) {
1286 1         5 die("ERROR: perlbrew root " . $self->root . " does not exist. Run `perlbrew init` to prepare it first.\n");
1287             }
1288              
1289 61 50       226 unless ($dist) {
1290 0         0 $self->run_command_help("install");
1291 0         0 exit(-1);
1292             }
1293              
1294 61         162 $self->{dist_name} = $dist; # for help msg generation, set to non
1295             # normalized name
1296              
1297 61         115 my ($dist_type, $dist_version);
1298 61 100       814 if (($dist_type, $dist_version) = $dist =~ /^(?:(c?perl)-?)?([\d._]+(?:-RC\d+)?|git|stable|blead)$/) {
    100          
    100          
    50          
1299 46 100       155 $dist_version = $self->resolve_stable_version if $dist_version eq 'stable';
1300 46   100     144 $dist_type ||= "perl";
1301 46         126 $dist = "${dist_type}-${dist_version}"; # normalize dist name
1302              
1303 46   66     265 my $installation_name = ($self->{as} || $dist) . $self->{variation} . $self->{append};
1304 46 100 66     246 if (not $self->{force} and $self->is_installed($installation_name)) {
1305 2         39 die "\nABORT: $installation_name is already installed.\n\n";
1306             }
1307              
1308 44 100 100     624 if ($dist_type eq 'perl' && $dist_version eq 'blead') {
1309 3         15 $self->do_install_blead();
1310             }
1311             else {
1312 41         439 $self->do_install_release($dist, $dist_version);
1313             }
1314              
1315             }
1316             # else it is some kind of special install:
1317             elsif (-d "$dist/.git") {
1318 1         5 $self->do_install_git($dist);
1319             }
1320             elsif (-f $dist) {
1321 13         54 $self->do_install_archive(App::Perlbrew::Path->new ($dist));
1322             }
1323             elsif ($dist =~ m/^(?:https?|ftp|file)/) { # more protocols needed?
1324 1         48 $self->do_install_url($dist);
1325             }
1326             else {
1327 0         0 die "Unknown installation target \"$dist\", abort.\nPlease see `perlbrew help` " .
1328             "for the instruction on using the install command.\n\n";
1329             }
1330              
1331 56 100       25765 if ($self->{switch}) {
1332 1 50       5 if (defined(my $installation_name = $self->{installation_name})) {
1333 1         6 $self->switch_to($installation_name)
1334             }
1335             else {
1336 0         0 warn "can't switch, unable to infer final destination name.\n\n";
1337             }
1338             }
1339 56         680 return;
1340             }
1341              
1342             sub check_and_calculate_variations {
1343 0     0 0 0 my $self = shift;
1344 0         0 my @both = @{$self->{both}};
  0         0  
1345              
1346 0 0       0 if ($self->{'all-variations'}) {
    0          
1347 0         0 @both = keys %flavor;
1348             }
1349             elsif ($self->{'common-variations'}) {
1350 0         0 push @both, grep $flavor{$_}{common}, keys %flavor;
1351             }
1352              
1353             # check the validity of the varitions given via 'both'
1354 0         0 for my $both (@both) {
1355 0 0       0 $flavor{$both} or die "$both is not a supported flavor.\n\n";
1356 0 0       0 $self->{$both} and die "options --both $both and --$both can not be used together";
1357 0 0       0 if (my $implied_by = $flavor{$both}{implied_by}) {
1358 0 0       0 $self->{$implied_by} and die "options --both $both and --$implied_by can not be used together";
1359             }
1360             }
1361              
1362             # flavors selected always
1363 0         0 my $start = '';
1364 0         0 $start .= "-$_" for grep $self->{$_}, keys %flavor;
1365              
1366             # make variations
1367 0         0 my @var = $start;
1368 0         0 for my $both (@both) {
1369 0         0 my $append = join('-', $both, grep defined, $flavor{$both}{implies});
1370 0         0 push @var, map "$_-$append", @var;
1371             }
1372              
1373             # normalize the variation names
1374 0         0 @var = map { join '-', '', sort { $flavor{$a}{ix} <=> $flavor{$b}{ix} } grep length, split /-+/, $_ } @var;
  0         0  
  0         0  
1375 0         0 s/(\b\w+\b)(?:-\1)+/$1/g for @var; # remove duplicate flavors
1376              
1377             # After inspecting perl Configure script this seems to be the most
1378             # reliable heuristic to determine if perl would have 64bit IVs by
1379             # default or not:
1380 0 0       0 if ($Config::Config{longsize} >= 8) {
1381             # We are in a 64bit platform. 64int and 64all are always set but
1382             # we don't want them to appear on the final perl name
1383 0         0 s/-64\w+//g for @var;
1384             }
1385              
1386             # remove duplicated variations
1387 0         0 my %var = map { $_ => 1 } @var;
  0         0  
1388 0         0 sort keys %var;
1389             }
1390              
1391             sub run_command_install_multiple {
1392 0     0 0 0 my ($self, @dists) = @_;
1393              
1394 0 0       0 unless (@dists) {
1395 0         0 $self->run_command_help("install-multiple");
1396 0         0 exit(-1);
1397             }
1398              
1399             die "--switch can not be used with command install-multiple.\n\n"
1400 0 0       0 if $self->{switch};
1401             die "--as can not be used when more than one distribution is given.\n\n"
1402 0 0 0     0 if $self->{as} and @dists > 1;
1403              
1404 0         0 my @variations = $self->check_and_calculate_variations;
1405 0 0       0 print join("\n",
1406             "Compiling the following distributions:",
1407             map(" $_$self->{append}", @dists),
1408             " with the following variations:",
1409             map((/-(.*)/ ? " $1" : " default"), @variations),
1410             "", "");
1411              
1412 0         0 my @ok;
1413 0         0 for my $dist (@dists) {
1414 0         0 for my $variation (@variations) {
1415 0         0 local $@;
1416 0         0 eval {
1417 0         0 $self->{$_} = '' for keys %flavor;
1418 0         0 $self->{$_} = 1 for split /-/, $variation;
1419 0         0 $self->{variation} = $variation;
1420 0         0 $self->{installation_name} = undef;
1421              
1422 0         0 $self->run_command_install($dist);
1423 0         0 push @ok, $self->{installation_name};
1424             };
1425 0 0       0 if ($@) {
1426 0         0 $@ =~ s/\n+$/\n/;
1427 0         0 print "Installation of $dist$variation failed: $@";
1428             }
1429             }
1430             }
1431              
1432 0         0 print join("\n",
1433             "",
1434             "The following perls have been installed:",
1435             map (" $_", grep defined, @ok),
1436             "", "");
1437             return
1438 0         0 }
1439              
1440             sub run_command_download {
1441 1     1 0 3 my ($self, $dist) = @_;
1442              
1443 1 50 33     12 $dist = $self->resolve_stable_version
1444             if $dist && $dist eq 'stable';
1445              
1446 1         4 my $rd = $self->release_detail($dist);
1447              
1448 1         2 my $dist_tarball = $rd->{tarball_name};
1449 1         3 my $dist_tarball_url = $rd->{tarball_url};
1450 1         2 my $dist_tarball_path = $self->root->dists ($dist_tarball);
1451              
1452 1 50 33     3 if (-f $dist_tarball_path && !$self->{force}) {
1453 0         0 print "$dist_tarball already exists\n";
1454             }
1455             else {
1456 1 50       9 print "Download $dist_tarball_url to $dist_tarball_path\n" unless $self->{quiet};
1457 1         6 my $error = http_download($dist_tarball_url, $dist_tarball_path);
1458 1 50       5 if ($error) {
1459 1         24 die "ERROR: Failed to download $dist_tarball_url\n$error\n";
1460             }
1461             }
1462             }
1463              
1464             sub purify {
1465 6     6 0 25 my ($self, $envname) = @_;
1466 6 50       21 my @paths = grep { index($_, $self->home) < 0 && index($_, $self->root) < 0 } split /:/, $self->env($envname);
  54         92  
1467 6 50       68 return wantarray ? @paths : join(":", @paths);
1468             }
1469              
1470             sub system_perl_executable {
1471 6     6 0 15 my ($self) = @_;
1472              
1473 6         9 my $system_perl_executable = do {
1474 6         27 local $ENV{PATH} = $self->pristine_path;
1475 6         94955 `perl -MConfig -e 'print \$Config{perlpath}'`
1476             };
1477              
1478 6         361 return $system_perl_executable;
1479             }
1480              
1481             sub system_perl_shebang {
1482 6     6 0 20 my ($self) = @_;
1483 6         204 return $Config{sharpbang}. $self->system_perl_executable;
1484             }
1485              
1486             sub pristine_path {
1487 6     6 0 19 my ($self) = @_;
1488 6         15 return $self->purify("PATH");
1489             }
1490              
1491             sub pristine_manpath {
1492 0     0 0 0 my ($self) = @_;
1493 0         0 return $self->purify("MANPATH");
1494             }
1495              
1496             sub run_command_display_system_perl_executable {
1497 0     0 0 0 print $_[0]->system_perl_executable . "\n";
1498             }
1499              
1500             sub run_command_display_system_perl_shebang {
1501 0     0 0 0 print $_[0]->system_perl_shebang . "\n";
1502             }
1503              
1504             sub run_command_display_pristine_path {
1505 0     0 0 0 print $_[0]->pristine_path . "\n";
1506             }
1507              
1508             sub run_command_display_pristine_manpath {
1509 0     0 0 0 print $_[0]->pristine_manpath . "\n";
1510             }
1511              
1512             sub do_install_archive {
1513 9     9 0 58 require File::Basename;
1514              
1515 9         17 my $self = shift;
1516 9         11 my $dist_tarball_path = shift;
1517 9         13 my $dist_version;
1518             my $installation_name;
1519              
1520 9 50       24 if ($dist_tarball_path->basename =~ m{(c?perl)-?(5.+)\.tar\.(gz|bz2|xz)\Z}) {
1521 9         23 my $perl_variant = $1;
1522 9         16 $dist_version = $2;
1523 9         18 $installation_name = "${perl_variant}-${dist_version}";
1524             }
1525              
1526 9 50 33     35 unless ($dist_version && $installation_name) {
1527 0         0 die "Unable to determine perl version from archive filename.\n\nThe archive name should look like perl-5.x.y.tar.gz or perl-5.x.y.tar.bz2 or perl-5.x.y.tar.xz\n";
1528             }
1529              
1530 9         26 my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path);
1531              
1532 9         177 $self->do_install_this($dist_extracted_path, $dist_version, $installation_name);
1533             }
1534              
1535             sub do_install_this {
1536 4     4 0 464 my ($self, $dist_extracted_dir, $dist_version, $installation_name) = @_;
1537              
1538 4         15 my $variation = $self->{variation};
1539 4         9 my $append = $self->{append};
1540 4         11 my $looks_like_we_are_installing_cperl = $dist_extracted_dir =~ /\/ cperl- /x;
1541              
1542 4         9 $self->{dist_extracted_dir} = $dist_extracted_dir;
1543 4         10 $self->{log_file} = $self->root->child("build.${installation_name}${variation}${append}.log");
1544              
1545 4         9 my @d_options = @{ $self->{D} };
  4         9  
1546 4         7 my @u_options = @{ $self->{U} };
  4         8  
1547 4         6 my @a_options = @{ $self->{A} };
  4         9  
1548 4         9 my $sitecustomize = $self->{sitecustomize};
1549 4         7 my $destdir = $self->{destdir};
1550 4 50       11 $installation_name = $self->{as} if $self->{as};
1551 4         9 $installation_name .= "$variation$append";
1552              
1553 4         10 $self->{installation_name} = $installation_name;
1554              
1555 4 100       10 if ($sitecustomize) {
1556 2 50       28 die "Could not read sitecustomize file '$sitecustomize'\n"
1557             unless -r $sitecustomize;
1558 2         9 push @d_options, "usesitecustomize";
1559             }
1560              
1561 4 50       22 if ($self->{noman}) {
1562 0         0 push @d_options, qw/man1dir=none man3dir=none/;
1563             }
1564              
1565 4         17 for my $flavor (keys %flavor) {
1566             $self->{$flavor} and push @d_options, $flavor{$flavor}{d_option}
1567 28 50       46 }
1568              
1569 4         11 my $perlpath = $self->root->perls($installation_name);
1570              
1571 4         37 unshift @d_options, qq(prefix=$perlpath);
1572 4 50       33 push @d_options, "usedevel" if $dist_version =~ /5\.\d[13579]|git|blead/;
1573              
1574 4 50       11 push @d_options, "usecperl" if $looks_like_we_are_installing_cperl;
1575              
1576 4         14 my $version = $self->comparable_perl_version($dist_version);
1577 4 50 33     20 if (defined $version and $version < $self->comparable_perl_version('5.6.0')) {
1578             # ancient perls do not support -A for Configure
1579 0         0 @a_options = ();
1580             } else {
1581 4 50       13 unless (grep { /eval:scriptdir=/} @a_options) {
  0         0  
1582 4         16 push @a_options, "'eval:scriptdir=${perlpath}/bin'";
1583             }
1584             }
1585              
1586 4         15 print "Installing $dist_extracted_dir into " . $self->root->perls ($installation_name)->stringify_with_tilde . "\n\n";
1587 4 50       34 print <{verbose};
1588             This could take a while. You can run the following command on another shell to track the status:
1589              
1590 4         16 tail -f ${\ $self->{log_file}->stringify_with_tilde }
1591              
1592             INSTALL
1593              
1594 4         24 my @preconfigure_commands = (
1595             "cd $dist_extracted_dir",
1596             "rm -f config.sh Policy.sh",
1597             );
1598              
1599 4 50 33     29 unless ($self->{"no-patchperl"} || $looks_like_we_are_installing_cperl) {
1600 4         13 my $patchperl = $self->root->bin("patchperl");
1601              
1602 4 50 33     37 unless (-x $patchperl && -f _) {
1603 4         11 $patchperl = "patchperl";
1604             }
1605              
1606 4         15 push @preconfigure_commands, 'chmod -R +w .', $patchperl;
1607             }
1608              
1609 4   50     14 my $configure_flags = $self->env("PERLBREW_CONFIGURE_FLAGS") || '-de';
1610              
1611             my @configure_commands = (
1612             "sh Configure $configure_flags " .
1613             join( ' ',
1614 6         28 ( map { qq{'-D$_'} } @d_options ),
1615 0         0 ( map { qq{'-U$_'} } @u_options ),
1616 4 50 33     17 ( map { qq{'-A$_'} } @a_options ),
  4         28  
1617             ),
1618             (defined $version and $version < $self->comparable_perl_version('5.8.9'))
1619             ? ("$^X -i -nle 'print unless /command-line/' makefile x2p/makefile")
1620             : ()
1621             );
1622              
1623 4   33     28 my $make = $ENV{MAKE} || ($^O eq "solaris" ? 'gmake' : 'make');
1624             my @build_commands = (
1625 4 50       17 $make . ' ' . ($self->{j} ? "-j$self->{j}" : "")
1626             );
1627              
1628             # Test via "make test_harness" if available so we'll get
1629             # automatic parallel testing via $HARNESS_OPTIONS. The
1630             # "test_harness" target was added in 5.7.3, which was the last
1631             # development release before 5.8.0.
1632 4         7 my $test_target = "test";
1633 4 50 33     44 if ($dist_version =~ /^5\.(\d+)\.(\d+)/
      33        
1634             && ($1 >= 8 || $1 == 7 && $2 == 3)) {
1635 4         9 $test_target = "test_harness";
1636             }
1637             local $ENV{TEST_JOBS}=$self->{j}
1638 4 50 50     72 if $test_target eq "test_harness" && ($self->{j}||1) > 1;
      33        
1639              
1640 4 100       27 my @install_commands = ("${make} install" . ($destdir ? " DESTDIR=$destdir" : q||));
1641 4 50       21 unshift @install_commands, "${make} $test_target" unless $self->{notest};
1642             # Whats happening here? we optionally join with && based on $self->{force}, but then subsequently join with && anyway?
1643 4 50       21 @install_commands = join " && ", @install_commands unless ($self->{force});
1644              
1645 4         14 my $cmd = join " && ",
1646             (
1647             @preconfigure_commands,
1648             @configure_commands,
1649             @build_commands,
1650             @install_commands
1651             );
1652              
1653 4         19 $self->{log_file}->unlink;
1654              
1655 4 50       21 if ($self->{verbose}) {
1656 0         0 $cmd = "($cmd) 2>&1 | tee $self->{log_file}";
1657 0 0       0 print "$cmd\n" if $self->{verbose};
1658             } else {
1659 4         27 $cmd = "($cmd) >> '$self->{log_file}' 2>&1 ";
1660             }
1661              
1662 4         57 delete $ENV{$_} for qw(PERL5LIB PERL5OPT AWKPATH NO_COLOR);
1663              
1664 4 100       18 if ($self->do_system($cmd)) {
1665 3         75 my $newperl = $self->root->perls ($installation_name)->perl;
1666 3 100       11 unless (-e $newperl) {
1667 2         9 $self->run_command_symlink_executables($installation_name);
1668             }
1669              
1670 3         9 eval { $self->append_log('##### Brew Finished #####') };
  3         12  
1671              
1672 3 100       18 if ($sitecustomize) {
1673 2         10 my $capture = $self->do_capture("$newperl -V:sitelib");
1674 2         1617 my ($sitelib) = $capture =~ m/sitelib='([^']*)';/;
1675 2 100       10 $sitelib = $destdir . $sitelib if $destdir;
1676 2         20 $sitelib = App::Perlbrew::Path->new($sitelib);
1677 2         8 $sitelib->mkpath;
1678 2         10 my $target = $sitelib->child ("sitecustomize.pl");
1679 2 50       16 open my $dst, ">", $target
1680             or die "Could not open '$target' for writing: $!\n";
1681 2 50       56 open my $src, "<", $sitecustomize
1682             or die "Could not open '$sitecustomize' for reading: $!\n";
1683 2         5 print {$dst} do { local $/; <$src> };
  2         5  
  2         7  
  2         74  
1684             }
1685              
1686 3         91 my $version_file =
1687             $self->root->perls ($installation_name)->version_file;
1688              
1689 3 50       11 if (-e $version_file) {
1690 0 0       0 $version_file->unlink()
1691             or die "Could not unlink $version_file file: $!\n";
1692             }
1693              
1694 3         134 print "$installation_name is successfully installed.\n";
1695             }
1696             else {
1697 1         40 eval { $self->append_log('##### Brew Failed #####') };
  1         3  
1698 1         5 die $self->INSTALLATION_FAILURE_MESSAGE;
1699             }
1700 3         28 return;
1701             }
1702              
1703             sub do_install_program_from_url {
1704 8     8 0 43 my ($self, $url, $program_name, $body_filter) = @_;
1705              
1706 8         24 my $out = $self->root->bin ($program_name);
1707              
1708 8 0 33     137 if (-f $out && !$self->{force} && !$self->{yes}) {
      33        
1709 0         0 require ExtUtils::MakeMaker;
1710              
1711 0         0 my $ans = ExtUtils::MakeMaker::prompt("\n$out already exists, are you sure to override ? [y/N]", "N");
1712              
1713 0 0       0 if ($ans !~ /^Y/i) {
1714 0 0       0 print "\n$program_name installation skipped.\n\n" unless $self->{quiet};
1715 0         0 return;
1716             }
1717             }
1718              
1719 8 100       56 my $body = http_get($url) or die "\nERROR: Failed to retrieve $program_name executable.\n\n";
1720              
1721 6 100       6519 unless ($body =~ m{\A#!/}s) {
1722 3   50     16 my $x = App::Perlbrew::Path->new ($self->env('TMPDIR') || "/tmp", "${program_name}.downloaded.$$");
1723 3         16 my $message = "\nERROR: The downloaded $program_name program seem to be invalid. Please check if the following URL can be reached correctly\n\n\t$url\n\n...and try again latter.";
1724              
1725 3 50       12 unless (-f $x) {
1726 3         39 open my $OUT, ">", $x;
1727 3         49 print $OUT $body;
1728 3         122 close($OUT);
1729 3         19 $message .= "\n\nThe previously downloaded file is saved at $x for manual inspection.\n\n";
1730             }
1731              
1732 3         55 die $message;
1733             }
1734              
1735 3 100 66     15 if ($body_filter && ref($body_filter) eq "CODE") {
1736 1         3 $body = $body_filter->($body);
1737             }
1738              
1739 3         27 $self->root->bin->mkpath;
1740 3 50       141 open my $OUT, '>', $out or die "cannot open file($out): $!";
1741 3         42 print $OUT $body;
1742 3         153 close $OUT;
1743 3         20 chmod 0755, $out;
1744 3 50       53 print "\n$program_name is installed to\n\n $out\n\n" unless $self->{quiet};
1745             }
1746              
1747             sub do_exit_with_error_code {
1748 0     0 0 0 my ($self, $code) = @_;
1749 0         0 exit($code);
1750             }
1751              
1752             sub do_system_with_exit_code {
1753 4     4 0 8 my ($self, @cmd) = @_;
1754 4         21862 return system(@cmd);
1755             }
1756              
1757             sub do_system {
1758 4     4 0 904 my ($self, @cmd) = @_;
1759 4         18 return ! $self->do_system_with_exit_code(@cmd);
1760             }
1761              
1762             sub do_capture {
1763 4     4 0 264 my ($self, @cmd) = @_;
1764             return Capture::Tiny::capture(
1765             sub {
1766 4     4   4334 $self->do_system(@cmd);
1767 4         221 });
1768             }
1769              
1770             sub format_perl_version {
1771 468     468 0 2456 my $self = shift;
1772 468         853 my $version = shift;
1773 468   100     5043 return sprintf "%d.%d.%d",
1774             substr($version, 0, 1),
1775             substr($version, 2, 3),
1776             substr($version, 5) || 0;
1777             }
1778              
1779             sub installed_perls {
1780 171     171 0 3244 my $self = shift;
1781              
1782 171         219 my @result;
1783 171         339 my $root = $self->root;
1784              
1785 171         522 for my $installation ($root->perls->list) {
1786 464         1482 my $name = $installation->name;
1787 464         1212 my $executable = $installation->perl;
1788 464 50       1288 next unless -f $executable;
1789              
1790 464         1960 my $version_file = $installation->version_file;
1791 464         1139 my $ctime = localtime((stat $executable)[ 10 ]); # localtime in scalar context!
1792              
1793 464         1225 my $orig_version;
1794 464 100       1456 if (-e $version_file) {
1795 432         3307 open my $fh, '<', $version_file;
1796 432         2109 local $/;
1797 432         7441 $orig_version = <$fh>;
1798 432         5138 chomp $orig_version;
1799             } else {
1800 32         124 $orig_version = `$executable -e 'print \$]'`;
1801 32 50 33     1681 if (defined $orig_version and length $orig_version) {
1802 32 50       3113 if (open my $fh, '>', $version_file ) {
1803 32         213 print {$fh} $orig_version;
  32         394  
1804             }
1805             }
1806             }
1807              
1808 464   100     3610 push @result, {
1809             name => $name,
1810             orig_version=> $orig_version,
1811             version => $self->format_perl_version($orig_version),
1812             is_current => ($self->current_perl eq $name) && !($self->current_lib),
1813             libs => [ $self->local_libs($name) ],
1814             executable => $executable,
1815             dir => $installation,
1816             comparable_version => $self->comparable_perl_version($orig_version),
1817             ctime => $ctime,
1818             };
1819             }
1820              
1821 171         1308 return sort { ( $self->{reverse}
1822             ? ( $a->{comparable_version} <=> $b->{comparable_version} or $b->{name} cmp $a->{name} )
1823 415 50 0     1711 : ( $b->{comparable_version} <=> $a->{comparable_version} or $a->{name} cmp $b->{name} ) ) } @result;
      33        
1824             }
1825              
1826             sub compose_locallib {
1827 8     8 0 27 my ($self, $perl_name, $lib_name) = @_;
1828 8         31 return join '@', $perl_name, $lib_name;
1829             }
1830              
1831             sub decompose_locallib {
1832 118     118 0 194 my ($self, $name) = @_;
1833 118         372 return split '@', $name;
1834             }
1835              
1836             sub enforce_localib {
1837 9     9 0 21 my ($self, $name) = @_;
1838 9 100       77 $name =~ s/^/@/ unless $name =~ m/@/;
1839 9         27 return $name;
1840             }
1841              
1842             sub local_libs {
1843 466     466 0 1866 my ($self, $perl_name) = @_;
1844              
1845 466         987 my $current = $self->current_env;
1846             my @libs = map {
1847 466         2184 my $name = $_->basename;
  39         143  
1848 39         97 my ($p, $l) = $self->decompose_locallib ($name);
1849             +{
1850 39         179 name => $name,
1851             is_current => $name eq $current,
1852             perl_name => $p,
1853             lib_name => $l,
1854             dir => $_,
1855             }
1856             } $self->home->child ("libs")->children;
1857 466 50       1507 if ($perl_name) {
1858 466         721 @libs = grep { $perl_name eq $_->{perl_name} } @libs;
  39         106  
1859             }
1860 466         1859 return @libs;
1861             }
1862              
1863             sub is_installed {
1864 132     132 0 718 my ($self, $name) = @_;
1865              
1866 132         297 return grep { $name eq $_->{name} } $self->installed_perls;
  349         1061  
1867             }
1868              
1869             sub assert_known_installation {
1870 0     0 0 0 my ($self, $name) = @_;
1871 0 0       0 return 1 if $self->is_installed($name);
1872 0         0 die "ERROR: The installation \"$name\" is unknown\n\n";
1873             }
1874              
1875             # Return a hash of PERLBREW_* variables
1876             sub perlbrew_env {
1877 31     31 0 59 my ($self, $name) = @_;
1878 31         41 my ($perl_name, $lib_name);
1879              
1880 31 50       56 if ($name) {
1881 31         74 ($perl_name, $lib_name) = $self->resolve_installation_name($name);
1882              
1883 31 50       65 unless ($perl_name) {
1884 0         0 die "\nERROR: The installation \"$name\" is unknown.\n\n";
1885             }
1886              
1887 31 50 66     65 unless (!$lib_name || grep { $_->{lib_name} eq $lib_name } $self->local_libs($perl_name)) {
  2         11  
1888 0         0 die "\nERROR: The lib name \"$lib_name\" is unknown.\n\n";
1889             }
1890             }
1891              
1892 31         101 my %env = (
1893             PERLBREW_VERSION => $VERSION,
1894             PERLBREW_PATH => $self->root->bin,
1895             PERLBREW_MANPATH => "",
1896             PERLBREW_ROOT => $self->root
1897             );
1898              
1899 31         1801 require local::lib;
1900 31         12110 my $pb_home = $self->home;
1901 31   50     66 my $current_local_lib_root = $self->env("PERL_LOCAL_LIB_ROOT") || "";
1902 31         138 my $current_local_lib_context = local::lib->new;
1903 31         232 my @perlbrew_local_lib_root = uniq(grep { /\Q${pb_home}\E/ } split(/:/, $current_local_lib_root));
  0         0  
1904 31 50       64 if ($current_local_lib_root =~ /^\Q${pb_home}\E/) {
1905 0         0 $current_local_lib_context = $current_local_lib_context->activate($_) for @perlbrew_local_lib_root;
1906             }
1907              
1908 31 50       66 if ($perl_name) {
1909 31         57 my $installation = $self->root->perls ($perl_name);
1910 31 50       69 if(-d $installation->child("bin")) {
1911 31         90 $env{PERLBREW_PERL} = $perl_name;
1912 31         90 $env{PERLBREW_PATH} .= ":" . $installation->child ("bin");
1913 31         103 $env{PERLBREW_MANPATH} = $installation->child ("man")
1914             }
1915              
1916 31 100       77 if ($lib_name) {
1917 2         5 $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root;
1918              
1919 2         7 my $base = $self->home->child ("libs", "${perl_name}\@${lib_name}");
1920              
1921 2 50       5 if (-d $base) {
1922 2         11 $current_local_lib_context = $current_local_lib_context->activate($base);
1923              
1924 2 100       38 if ($self->env('PERLBREW_LIB_PREFIX')) {
1925             unshift
1926 1         2 @{$current_local_lib_context->libs},
  1         3  
1927             $self->env('PERLBREW_LIB_PREFIX');
1928             }
1929              
1930 2         7 $env{PERLBREW_PATH} = $base->child ("bin") . ":" . $env{PERLBREW_PATH};
1931 2         8 $env{PERLBREW_MANPATH} = $base->child ("man") . ":" . $env{PERLBREW_MANPATH};
1932 2         7 $env{PERLBREW_LIB} = $lib_name;
1933             }
1934             } else {
1935 29         57 $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root;
1936 29         48 $env{PERLBREW_LIB} = undef;
1937             }
1938              
1939 31         93 my %ll_env = $current_local_lib_context->build_environment_vars;
1940 31         1322 delete $ll_env{PATH};
1941 31         74 for my $key (keys %ll_env) {
1942 66         152 $env{$key} = $ll_env{$key};
1943             }
1944             } else {
1945 0         0 $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root;
1946              
1947 0         0 my %ll_env = $current_local_lib_context->build_environment_vars;
1948 0         0 delete $ll_env{PATH};
1949 0         0 for my $key (keys %ll_env) {
1950 0         0 $env{$key} = $ll_env{$key};
1951             }
1952 0         0 $env{PERLBREW_LIB} = undef;
1953 0         0 $env{PERLBREW_PERL} = undef;
1954             }
1955              
1956 31         237 return %env;
1957             }
1958              
1959             sub run_command_list {
1960 5     5 0 13 my $self = shift;
1961 5         12 my $is_verbose = $self->{verbose};
1962              
1963 5 100       13 if ($self->{'no-decoration'}) {
1964 2         12 for my $i ($self->installed_perls) {
1965 8         123 print $i->{name} . "\n";
1966 8         17 for my $lib (@{$i->{libs}}) {
  8         24  
1967 2         20 print $lib->{name} . "\n";
1968             }
1969             }
1970             } else {
1971 3         13 for my $i ($self->installed_perls) {
1972             printf "%-2s%-20s %-20s %s\n",
1973             $i->{is_current} ? '*' : '',
1974             $i->{name},
1975             ( $is_verbose ?
1976 12 100       197 (index($i->{name}, $i->{version}) < 0) ? "($i->{version})" : ''
    0          
    50          
    50          
1977             : '' ),
1978             ( $is_verbose ? "(installed on $i->{ctime})" : '' );
1979              
1980 12         31 for my $lib (@{$i->{libs}}) {
  12         32  
1981             print $lib->{is_current} ? "* " : " ",
1982 4 100       40 $lib->{name}, "\n"
1983             }
1984             }
1985             }
1986              
1987 5         86 return 0;
1988             }
1989              
1990             sub launch_sub_shell {
1991 0     0 0 0 my ($self, $name) = @_;
1992 0         0 my $shell = $self->env('SHELL');
1993              
1994 0         0 my $shell_opt = "";
1995              
1996 0 0       0 if ($shell =~ /\/zsh\d?$/) {
1997 0         0 $shell_opt = "-d -f";
1998              
1999 0 0       0 if ($^O eq 'darwin') {
2000 0         0 my $root_dir = $self->root;
2001 0         0 print <<"WARNINGONMAC"
2002             --------------------------------------------------------------------------------
2003             WARNING: zsh perlbrew sub-shell is not working on Mac OSX Lion.
2004              
2005             It is known that on MacOS Lion, zsh always resets the value of PATH on launching
2006             a sub-shell. Effectively nullify the changes required by perlbrew sub-shell. You
2007             may `echo \$PATH` to examine it and if you see perlbrew related paths are in the
2008             end, instead of in the beginning, you are unfortunate.
2009              
2010             You are advised to include the following line to your ~/.zshenv as a better
2011             way to work with perlbrew:
2012              
2013             source $root_dir/etc/bashrc
2014              
2015             --------------------------------------------------------------------------------
2016             WARNINGONMAC
2017              
2018             }
2019             }
2020              
2021 0         0 my %env = ($self->perlbrew_env($name), PERLBREW_SKIP_INIT => 1);
2022              
2023 0 0       0 unless ($ENV{PERLBREW_VERSION}) {
2024 0         0 my $root = $self->root;
2025             # The user does not source bashrc/csh in their shell initialization.
2026 0         0 $env{PATH} = $env{PERLBREW_PATH} . ":" . join ":", grep { !/$root\/bin/ } split ":", $ENV{PATH};
  0         0  
2027 0         0 $env{MANPATH} = $env{PERLBREW_MANPATH} . ":" . join ":", grep { !/$root\/man/ }
2028 0 0       0 ( defined($ENV{MANPATH}) ? split(":", $ENV{MANPATH}) : () );
2029             }
2030              
2031 0         0 my $command = "env ";
2032 0         0 while (my ($k, $v) = each(%env)) {
2033 58     58   613 no warnings "uninitialized";
  58         125  
  58         278732  
2034 0         0 $command .= "$k=\"$v\" ";
2035             }
2036 0         0 $command .= " $shell $shell_opt";
2037              
2038 0 0       0 my $pretty_name = defined($name) ? $name : "the default perl";
2039 0         0 print "\nA sub-shell is launched with $pretty_name as the activated perl. Run 'exit' to finish it.\n\n";
2040 0         0 exec($command);
2041             }
2042              
2043             sub run_command_use {
2044 0     0 0 0 my $self = shift;
2045 0         0 my $perl = shift;
2046              
2047 0 0       0 if ( !$perl ) {
2048 0         0 my $current = $self->current_env;
2049 0 0       0 if ($current) {
2050 0         0 print "Currently using $current\n";
2051             } else {
2052 0         0 print "No version in use; defaulting to system\n";
2053             }
2054 0         0 return;
2055             }
2056              
2057 0         0 $self->launch_sub_shell($perl);
2058              
2059             }
2060              
2061             sub run_command_switch {
2062 0     0 0 0 my ($self, $dist, $alias) = @_;
2063              
2064 0 0       0 unless ( $dist ) {
2065 0         0 my $current = $self->current_env;
2066 0 0       0 printf "Currently switched %s\n",
2067             ( $current ? "to $current" : 'off' );
2068 0         0 return;
2069             }
2070              
2071 0         0 $self->switch_to($dist, $alias);
2072             }
2073              
2074             sub switch_to {
2075 0     0 0 0 my ($self, $dist, $alias) = @_;
2076              
2077 0 0 0     0 die "Cannot use for alias something that starts with 'perl-'\n"
2078             if $alias && $alias =~ /^perl-/;
2079              
2080 0 0       0 die "${dist} is not installed\n" unless -d $self->root->perls ($dist);
2081              
2082 0 0 0     0 if ($self->env("PERLBREW_SHELLRC_VERSION") && $self->current_shell_is_bashish) {
2083 0         0 local $ENV{PERLBREW_PERL} = $dist;
2084 0         0 my $HOME = $self->env('HOME');
2085 0         0 my $pb_home = $self->home;
2086              
2087 0         0 $pb_home->mkpath;
2088 0         0 system("$0 env $dist > " . $pb_home->child ("init"));
2089              
2090 0         0 print "Switched to $dist.\n\n";
2091             }
2092             else {
2093 0         0 $self->launch_sub_shell($dist);
2094             }
2095             }
2096              
2097             sub run_command_off {
2098 0     0 0 0 my $self = shift;
2099 0         0 $self->launch_sub_shell;
2100             }
2101              
2102             sub run_command_switch_off {
2103 0     0 0 0 my $self = shift;
2104 0         0 my $pb_home = $self->home;
2105              
2106 0         0 $pb_home->mkpath;
2107 0         0 system("env PERLBREW_PERL= $0 env > " . $pb_home->child ("init"));
2108              
2109 0         0 print "\nperlbrew is switched off. Please exit this shell and start a new one to make it effective.\n";
2110 0         0 print "To immediately make it effective, run this line in this terminal:\n\n exec @{[ $self->env('SHELL') ]}\n\n";
  0         0  
2111             }
2112              
2113             sub run_command_env {
2114 3     3 0 9 my($self, $name) = @_;
2115              
2116 3         12 my %env = $self->perlbrew_env($name);
2117              
2118 3         9 my @statements;
2119 3         25 for my $k (sort keys %env) {
2120 28         38 my $v = $env{$k};
2121 28 100 100     126 if (defined($v) && $v ne '') {
2122 25         36 $v =~ s/(\\")/\\$1/g;
2123 25         56 push @statements, ["set", $k, $v];
2124             } else {
2125 3         13 push @statements, ["unset", $k];
2126             }
2127             }
2128              
2129 3 50       8 if ($self->env('SHELL') =~ /(ba|k|z|\/)sh\d?$/) {
2130 3         9 for (@statements) {
2131 28         66 my ($o, $k, $v) = @$_;
2132 28 100       46 if ($o eq 'unset') {
2133 3         156 print "unset $k\n";
2134             } else {
2135 25         44 $v =~ s/(\\")/\\$1/g;
2136 25         379 print "export $k=\"$v\"\n";
2137             }
2138             }
2139             } else {
2140 0         0 for (@statements) {
2141 0         0 my ($o, $k, $v) = @$_;
2142 0 0       0 if ($o eq 'unset') {
2143 0         0 print "unsetenv $k\n";
2144             } else {
2145 0         0 print "setenv $k \"$v\"\n";
2146             }
2147             }
2148             }
2149             }
2150              
2151             sub run_command_symlink_executables {
2152 2     2 0 7 my($self, @perls) = @_;
2153 2         4 my $root = $self->root;
2154              
2155 2 50       7 unless (@perls) {
2156 0 0       0 @perls = map { $_->name } grep { -d $_ && ! -l $_ } $root->perls->list;
  0         0  
  0         0  
2157             }
2158              
2159 2         5 for my $perl (@perls) {
2160 2         14 for my $executable ($root->perls ($perl)->bin->children) {
2161 0         0 my ($name, $version) = $executable =~ m/bin\/(.+?)(5\.\d.*)?$/;
2162 0 0       0 next unless $version;
2163              
2164 0         0 $executable->symlink ($root->perls ($perl)->bin($name));
2165 0 0       0 $executable->symlink ($root->perls ($perl)->perl) if $name eq "cperl";
2166             }
2167             }
2168             }
2169              
2170             sub run_command_install_patchperl {
2171 2     2 0 4 my ($self) = @_;
2172             $self->do_install_program_from_url(
2173             'https://raw.githubusercontent.com/gugod/patchperl-packing/master/patchperl',
2174             'patchperl',
2175             sub {
2176 1     1   2 my ($body) = @_;
2177 1         6 $body =~ s/\A#!.+?\n/ $self->system_perl_shebang . "\n" /se;
  1         4  
2178 1         17 return $body;
2179             }
2180 2         14 );
2181             }
2182              
2183             sub run_command_install_cpanm {
2184 3     3 0 9 my ($self) = @_;
2185 3         10 $self->do_install_program_from_url('https://raw.githubusercontent.com/miyagawa/cpanminus/master/cpanm' => 'cpanm');
2186             }
2187              
2188             sub run_command_install_cpm {
2189 3     3 0 7 my ($self) = @_;
2190 3         25 $self->do_install_program_from_url('https://raw.githubusercontent.com/skaji/cpm/master/cpm' => 'cpm');
2191             }
2192              
2193             sub run_command_self_upgrade {
2194 0     0 0 0 my ($self) = @_;
2195              
2196 0         0 require FindBin;
2197 0 0       0 unless (-w $FindBin::Bin) {
2198 0         0 die "Your perlbrew installation appears to be system-wide. Please upgrade through your package manager.\n";
2199             }
2200              
2201 0   0     0 my $TMPDIR = $ENV{TMPDIR} || "/tmp";
2202 0         0 my $TMP_PERLBREW = App::Perlbrew::Path->new ($TMPDIR, "perlbrew");
2203              
2204 0         0 http_download('https://raw.githubusercontent.com/gugod/App-perlbrew/master/perlbrew', $TMP_PERLBREW);
2205              
2206 0         0 chmod 0755, $TMP_PERLBREW;
2207 0         0 my $new_version = qx($TMP_PERLBREW version);
2208 0         0 chomp $new_version;
2209 0 0       0 if ($new_version =~ /App::perlbrew\/(\d+\.\d+)$/) {
2210 0         0 $new_version = $1;
2211             } else {
2212 0         0 $TMP_PERLBREW->unlink;
2213 0         0 die "Unable to detect version of new perlbrew!\n";
2214             }
2215              
2216 0 0       0 if ($new_version <= $VERSION) {
2217 0 0       0 print "Your perlbrew is up-to-date (version $VERSION).\n" unless $self->{quiet};
2218 0         0 $TMP_PERLBREW->unlink;
2219 0         0 return;
2220             }
2221              
2222 0 0       0 print "Upgrading from $VERSION to $new_version\n" unless $self->{quiet};
2223              
2224 0         0 system $TMP_PERLBREW, "self-install";
2225 0         0 $TMP_PERLBREW->unlink;
2226             }
2227              
2228             sub run_command_uninstall {
2229 0     0 0 0 my ($self, $target) = @_;
2230              
2231 0 0       0 unless ($target) {
2232 0         0 $self->run_command_help("uninstall");
2233 0         0 exit(-1);
2234             }
2235              
2236 0         0 my @installed = $self->installed_perls(@_);
2237              
2238 0         0 my ($to_delete) = grep { $_->{name} eq $target } @installed;
  0         0  
2239              
2240 0 0       0 die "'$target' is not installed\n" unless $to_delete;
2241              
2242 0         0 my @dir_to_delete;
2243 0         0 for (@{$to_delete->{libs}}) {
  0         0  
2244 0         0 push @dir_to_delete, $_->{dir};
2245             }
2246 0         0 push @dir_to_delete, $to_delete->{dir};
2247              
2248 0 0       0 my $ans = ($self->{yes}) ? "Y": undef;
2249 0 0       0 if (!defined($ans)) {
2250 0         0 require ExtUtils::MakeMaker;
2251 0         0 $ans = ExtUtils::MakeMaker::prompt("\nThe following perl+lib installation(s) will be deleted:\n\n\t" . join("\n\t", @dir_to_delete) . "\n\n... are you sure ? [y/N]", "N");
2252             }
2253              
2254 0 0       0 if ($ans =~ /^Y/i) {
2255 0         0 for (@dir_to_delete) {
2256 0 0       0 print "Deleting: $_\n" unless $self->{quiet};
2257 0         0 App::Perlbrew::Path->new ($_)->rmpath;
2258 0 0       0 print "Deleted: $_\n" unless $self->{quiet};
2259             }
2260             } else {
2261 0         0 print "\nOK. Not deleting anything.\n\n";
2262 0         0 return;
2263             }
2264             }
2265              
2266             sub run_command_exec {
2267 17     17 0 39 my $self = shift;
2268 17         32 my %opts;
2269              
2270 17         26 local (@ARGV) = @{$self->{original_argv}};
  17         64  
2271              
2272 17         66 Getopt::Long::Configure ('require_order');
2273 17         452 my @command_options = ('with=s', 'halt-on-error', 'min=s', 'max=s');
2274              
2275 17         54 $self->parse_cmdline (\%opts, @command_options);
2276 17         27965 shift @ARGV; # "exec"
2277 17         55 $self->parse_cmdline (\%opts, @command_options);
2278              
2279 17         29098 my @exec_with;
2280 17 100       46 if ($opts{with}) {
2281 14         36 my %installed = map { $_->{name} => $_ } map { ($_, @{$_->{libs}}) } $self->installed_perls;
  56         112  
  56         61  
  56         86  
2282              
2283 14 100       433 my $d = ($opts{with} =~ m/ /) ? qr( +) : qr(,+);
2284 21         39 my @with = grep { $_ } map {
2285 21         52 my ($p, $l) = $self->resolve_installation_name($_);
2286 21 50       45 $p .= "\@$l" if $l;
2287 21         41 $p;
2288 14         78 } split $d, $opts{with};
2289              
2290 14         26 @exec_with = map { $installed{$_} } @with;
  20         106  
2291             } else {
2292             @exec_with = grep {
2293 12         32 not -l $self->root->perls( $_->{name} ); # Skip Aliases
2294 3         58 } map { ($_, @{$_->{libs}}) } $self->installed_perls;
  12         16  
  12         21  
2295             }
2296              
2297 17 100       43 if ($opts{min}) {
2298             # TODO use comparable version.
2299             # For now, it doesn't produce consistent results for 5.026001 and 5.26.1
2300 1         4 @exec_with = grep { $_->{orig_version} >= $opts{min} } @exec_with;
  4         16  
2301             }
2302              
2303 17 100       34 if ($opts{max}) {
2304 1         4 @exec_with = grep { $_->{orig_version} <= $opts{max} } @exec_with;
  4         15  
2305             }
2306              
2307 17 50       39 if (0 == @exec_with) {
2308 0 0       0 print "No perl installation found.\n" unless $self->{quiet};
2309             }
2310              
2311 17         24 my $no_header = 0;
2312 17 100       41 if (1 == @exec_with) {
2313 9         10 $no_header = 1;
2314             }
2315              
2316 17         29 my $overall_success = 1;
2317 17         31 for my $i ( @exec_with ) {
2318 28         81 my %env = $self->perlbrew_env($i->{name});
2319 28 50       70 next if !$env{PERLBREW_PERL};
2320              
2321 28         1128 local %ENV = %ENV;
2322 28 100       314 $ENV{$_} = defined $env{$_} ? $env{$_} : '' for keys %env;
2323 28         105 $ENV{PATH} = join(':', $env{PERLBREW_PATH}, $ENV{PATH});
2324 28   50     116 $ENV{MANPATH} = join(':', $env{PERLBREW_MANPATH}, $ENV{MANPATH}||"");
2325 28   50     84 $ENV{PERL5LIB} = $env{PERL5LIB} || "";
2326              
2327 28 50 66     680 print "$i->{name}\n==========\n" unless $no_header || $self->{quiet};
2328              
2329 28 100       138 if (my $err = $self->do_system_with_exit_code(@ARGV)) {
2330 8         499 my $exit_code = $err >> 8;
2331             # return 255 for case when process was terminated with signal, in that case real exit code is useless and weird
2332 8 100       17 $exit_code = 255 if $exit_code > 255;
2333 8         11 $overall_success = 0;
2334              
2335 8 100       20 unless ($self->{quiet}) {
2336 7         182 print "Command terminated with non-zero status.\n";
2337              
2338             print STDERR "Command [" .
2339 7 100       28 join(' ', map { /\s/ ? "'$_'" : $_ } @ARGV) . # trying reverse shell escapes - quote arguments containing spaces
  21         189  
2340             "] terminated with exit code $exit_code (\$? = $err) under the following perl environment:\n";
2341 7         38 print STDERR $self->format_info_output;
2342             }
2343              
2344 8 100       230 $self->do_exit_with_error_code($exit_code) if ($opts{'halt-on-error'});
2345             }
2346 25 100 100     1644 print "\n" unless $self->{quiet} || $no_header;
2347             }
2348 14 100       104 $self->do_exit_with_error_code(1) unless $overall_success;
2349             }
2350              
2351             sub run_command_clean {
2352 0     0 0 0 my ($self) = @_;
2353 0         0 my $root = $self->root;
2354 0         0 my @build_dirs = $root->build->children;
2355              
2356 0         0 for my $dir (@build_dirs) {
2357 0         0 print "Removing $dir\n";
2358 0         0 App::Perlbrew::Path->new ($dir)->rmpath;
2359             }
2360              
2361 0         0 my @tarballs = $root->dists->children;
2362 0         0 for my $file ( @tarballs ) {
2363 0         0 print "Removing $file\n";
2364 0         0 $file->unlink;
2365             }
2366              
2367 0         0 print "\nDone\n";
2368             }
2369              
2370             sub run_command_alias {
2371 1     1 0 3 my ($self, $cmd, $name, $alias) = @_;
2372              
2373 1 50       3 unless ($cmd) {
2374 0         0 $self->run_command_help("alias");
2375 0         0 exit(-1);
2376             }
2377              
2378 1 50       3 my $path_name = $self->root->perls ($name) if $name;
2379 1 50       2 my $path_alias = $self->root->perls ($alias) if $alias;
2380              
2381 1 0 33     3 if ($alias && -e $path_alias && !-l $path_alias) {
      33        
2382 0         0 die "\nABORT: The installation name `$alias` is not an alias, cannot override.\n\n";
2383             }
2384              
2385 1 50       7 if ($cmd eq 'create') {
    50          
    50          
    50          
2386 0         0 $self->assert_known_installation($name);
2387              
2388 0 0 0     0 if ($self->is_installed($alias) && !$self->{force}) {
2389 0         0 die "\nABORT: The installation `${alias}` already exists. Cannot override.\n\n";
2390             }
2391              
2392 0         0 $path_alias->unlink;
2393 0         0 $path_name->symlink ($path_alias);
2394             } elsif ($cmd eq 'delete') {
2395 0         0 $self->assert_known_installation($name);
2396              
2397 0 0       0 unless (-l $path_name) {
2398 0         0 die "\nABORT: The installation name `$name` is not an alias, cannot remove.\n\n";
2399             }
2400              
2401 0         0 $path_name->unlink;
2402             } elsif ($cmd eq 'rename') {
2403 0         0 $self->assert_known_installation($name);
2404              
2405 0 0       0 unless (-l $path_name) {
2406 0         0 die "\nABORT: The installation name `$name` is not an alias, cannot rename.\n\n";
2407             }
2408              
2409 0 0 0     0 if (-l $path_alias && !$self->{force}) {
2410 0         0 die "\nABORT: The alias `$alias` already exists, cannot rename to it.\n\n";
2411             }
2412              
2413 0         0 rename($path_name, $path_alias);
2414             } elsif ($cmd eq 'help') {
2415 0         0 $self->run_command_help("alias");
2416             } else {
2417 1         8 die "\nERROR: Unrecognized action: `${cmd}`.\n\n";
2418             }
2419             }
2420              
2421             sub run_command_display_bashrc {
2422 0     0 0 0 print BASHRC_CONTENT();
2423             }
2424              
2425             sub run_command_display_cshrc {
2426 0     0 0 0 print CSHRC_CONTENT();
2427             }
2428              
2429             sub run_command_display_installation_failure_message {
2430 0     0 0 0 my ($self) = @_;
2431             }
2432              
2433             sub run_command_lib {
2434 12     12 0 54 my ($self, $subcommand, @args) = @_;
2435              
2436 12 50       80 unless ($subcommand) {
2437 0         0 $self->run_command_help("lib");
2438 0         0 exit(-1);
2439             }
2440              
2441 12         44 my $sub = "run_command_lib_$subcommand";
2442 12 100       97 if ($self->can($sub)) {
2443 11         42 $self->$sub(@args);
2444             } else {
2445 1         64 print "Unknown command: $subcommand\n";
2446             }
2447             }
2448              
2449             sub run_command_lib_create {
2450 8     8 0 27 my ($self, $name) = @_;
2451              
2452 8 100       32 die "ERROR: No lib name\n", $self->run_command_help("lib", undef, 'return_text') unless $name;
2453              
2454 7         31 $name = $self->enforce_localib ($name);
2455              
2456 7         30 my ($perl_name, $lib_name) = $self->resolve_installation_name($name);
2457              
2458 7 100       27 if (!$perl_name) {
2459 1         14 my ($perl_name, $lib_name) = $self->decompose_locallib ($name);
2460 1         18 die "ERROR: '$perl_name' is not installed yet, '$name' cannot be created.\n";
2461             }
2462              
2463 6         26 my $fullname = $self->compose_locallib ($perl_name, $lib_name);
2464 6         61 my $dir = $self->home->child ("libs", $fullname);
2465              
2466 6 50       32 if (-d $dir) {
2467 0         0 die "$fullname is already there.\n";
2468             }
2469              
2470 6         42 $dir->mkpath;
2471              
2472 6 50       439 print "lib '$fullname' is created.\n" unless $self->{quiet};
2473              
2474 6         83 return;
2475             }
2476              
2477             sub run_command_lib_delete {
2478 3     3 0 10 my ($self, $name) = @_;
2479              
2480 3 100       11 die "ERROR: No lib to delete\n", $self->run_command_help("lib", undef, 'return_text') unless $name;
2481              
2482 2         15 $name = $self->enforce_localib ($name);
2483              
2484 2         10 my ($perl_name, $lib_name) = $self->resolve_installation_name($name);
2485              
2486 2         15 my $fullname = $self->compose_locallib ($perl_name, $lib_name);
2487              
2488 2         6 my $current = $self->current_env;
2489              
2490 2         61 my $dir = $self->home->child ("libs", $fullname);
2491              
2492 2 100       5 if (-d $dir) {
2493              
2494 1 50       5 if ($fullname eq $current) {
2495 0         0 die "$fullname is currently being used in the current shell, it cannot be deleted.\n";
2496             }
2497              
2498 1         5 $dir->rmpath;
2499              
2500             print "lib '$fullname' is deleted.\n"
2501 1 50       48 unless $self->{quiet};
2502             } else {
2503 1         19 die "ERROR: '$fullname' does not exist.\n";
2504             }
2505              
2506 1         14 return;
2507             }
2508              
2509             sub run_command_lib_list {
2510 0     0 0 0 my ($self) = @_;
2511 0         0 my $dir = $self->home->child ("libs");
2512 0 0       0 return unless -d $dir;
2513              
2514 0 0       0 opendir my $dh, $dir or die "open $dir failed: $!";
2515 0 0       0 my @libs = grep { !/^\./ && /\@/ } readdir($dh);
  0         0  
2516              
2517 0         0 my $current = $self->current_env;
2518 0         0 for (@libs) {
2519 0 0       0 print $current eq $_ ? "* " : " ";
2520 0         0 print "$_\n";
2521             }
2522             }
2523              
2524             sub run_command_upgrade_perl {
2525 0     0 0 0 my ($self) = @_;
2526              
2527 0         0 my $PERL_VERSION_RE = qr/(\d+)\.(\d+)\.(\d+)/;
2528              
2529 0         0 my ($current) = grep { $_->{is_current} } $self->installed_perls;
  0         0  
2530              
2531 0 0       0 unless (defined $current) {
2532 0         0 print "no perlbrew environment is currently in use\n";
2533 0         0 exit(1);
2534             }
2535              
2536 0         0 my ($major, $minor, $release);
2537              
2538 0 0       0 if ($current->{version} =~ /^$PERL_VERSION_RE$/) {
2539 0         0 ($major, $minor, $release) = ($1, $2, $3);
2540             } else {
2541 0         0 print "unable to parse version '$current->{version}'\n";
2542 0         0 exit(1);
2543             }
2544              
2545             my @available = grep {
2546 0         0 /^perl-$major\.$minor/
  0         0  
2547             } $self->available_perls;
2548              
2549 0         0 my $latest_available_perl = $release;
2550              
2551 0         0 foreach my $perl (@available) {
2552 0 0       0 if ($perl =~ /^perl-$PERL_VERSION_RE$/) {
2553 0         0 my $this_release = $3;
2554 0 0       0 if ($this_release > $latest_available_perl) {
2555 0         0 $latest_available_perl = $this_release;
2556             }
2557             }
2558             }
2559              
2560 0 0       0 if ($latest_available_perl == $release) {
2561 0         0 print "This perlbrew environment ($current->{name}) is already up-to-date.\n";
2562 0         0 exit(0);
2563             }
2564              
2565 0         0 my $dist_version = "$major.$minor.$latest_available_perl";
2566 0         0 my $dist = "perl-$dist_version";
2567              
2568 0 0       0 print "Upgrading $current->{name} to $dist_version\n" unless $self->{quiet};
2569 0         0 local $self->{as} = $current->{name};
2570 0         0 local $self->{dist_name} = $dist;
2571              
2572 0         0 my @d_options = map { '-D' . $flavor{$_}->{d_option}} keys %flavor ;
  0         0  
2573 0         0 my %sub_config = map { $_ => $Config{$_}} grep { /^config_arg\d/} keys %Config ;
  0         0  
  0         0  
2574 0         0 for my $value (values %sub_config) {
2575 0         0 my $value_wo_D = $value;
2576 0         0 $value_wo_D =~ s/^-D//;
2577 0 0       0 push @{$self->{D}} , $value_wo_D if grep {/$value/} @d_options;
  0         0  
  0         0  
2578             }
2579              
2580 0         0 $self->do_install_release($dist, $dist_version);
2581             }
2582              
2583             sub list_modules {
2584 1     1 0 7 my ($self, $env) = @_;
2585              
2586 1   33     9 $env ||= $self->current_env;
2587             my ($stdout, $stderr, $success) = Capture::Tiny::capture(
2588             sub {
2589 1     1   1207 __PACKAGE__->new(
2590             "--quiet", "exec", "--with", $env, 'perl', '-MExtUtils::Installed', '-le',
2591             'BEGIN{@INC=grep {$_ ne q!.!} @INC}; print for ExtUtils::Installed->new->modules;',
2592             )->run;
2593             }
2594 1         28 );
2595              
2596 1 50       838 unless ($success) {
2597 0 0       0 unless ($self->{quiet}) {
2598 0         0 print STDERR "Failed to retrive the list of installed modules.\n";
2599 0 0       0 if ($self->{verbose}) {
2600 0         0 print STDERR "STDOUT\n======\n$stdout\nSTDERR\n======\n$stderr\n";
2601             }
2602             }
2603 0         0 return [];
2604             }
2605              
2606 1         8 my %rename = (
2607             "ack" => "App::Ack",
2608             "libwww::perl" => "LWP",
2609             "libintl-perl" => "Locale::Messages",
2610             "Role::Identifiable" => "Role::Identifiable::HasTags",
2611             "TAP::Harness::Multiple" => "TAP::Harness::ReportByDescription",
2612             );
2613              
2614 1   33     4 return [map { $rename{$_} // $_ } grep { $_ ne "Perl" } split(/\n/, $stdout)];
  1         14  
  1         4  
2615             }
2616              
2617             sub run_command_list_modules {
2618 0     0 0 0 my ($self) = @_;
2619 0         0 my ($modules, $error) = $self->list_modules();
2620 0         0 print "$_\n" for @$modules;
2621             }
2622              
2623             sub resolve_installation_name {
2624 79     79 0 1661 my ($self, $name) = @_;
2625 79 100       181 die "App::perlbrew->resolve_installation_name requires one argument." unless $name;
2626              
2627 78         188 my ($perl_name, $lib_name) = $self->decompose_locallib ($name);
2628 78 100       173 $perl_name = $name unless $lib_name;
2629 78   66     193 $perl_name ||= $self->current_perl;
2630              
2631 78 100       392 if (!$self->is_installed($perl_name)) {
2632 6 100       27 if ($self->is_installed("perl-${perl_name}") ) {
2633 3         9 $perl_name = "perl-${perl_name}";
2634             }
2635             else {
2636 3         44 return undef;
2637             }
2638             }
2639              
2640 75 100       816 return wantarray ? ($perl_name, $lib_name) : $perl_name;
2641             }
2642              
2643             # Implementation of the 'clone-modules' command.
2644             #
2645             # This method accepts a destination and source installation
2646             # of Perl to clone modules from and into.
2647             # For instance calling
2648             # $app->run_command_clone_modules($perl_a, $perl_b);
2649             # installs all modules that have been installed on Perl A
2650             # to the instance of Perl B.
2651             # The source instance is optional, that is if the method
2652             # is invoked with a single argument, the currently
2653             # running instance is used as source. Therefore the
2654             # two following calls are the same:
2655             #
2656             # $app->run_command_clone_modules( $self->current_perl, $perl_b );
2657             # $app->run_command_clone_modules( $perl_b );
2658             #
2659             # Of course, both Perl installation must exist on this
2660             # perlbrew enviroment.
2661             #
2662             # The method extracts the modules installed on the source Perl
2663             # instance and put them on a temporary file, such file is then
2664             # passed to another instance of the application to
2665             # execute cpanm on it. The final result is the installation
2666             # of source modules into the destination instance.
2667             sub run_command_clone_modules {
2668 4     4 0 8 my $self = shift;
2669              
2670             # default to use the currently installation
2671 4         17 my ( $dst_perl, $src_perl );
2672              
2673             # the first argument is the destination, the second
2674             # optional argument is the source version, default
2675             # to use the current installation
2676 4   33     8 $dst_perl = pop || $self->current_env;
2677 4   66     30 $src_perl = pop || $self->current_env;
2678              
2679             # check source and destination do exist
2680 4 50       108 undef $src_perl if (! $self->resolve_installation_name($src_perl));
2681 4 50       29 undef $dst_perl if (! $self->resolve_installation_name($dst_perl));
2682              
2683 4 50 33     53 if ( ! $src_perl
      33        
2684             || ! $dst_perl
2685             || $src_perl eq $dst_perl ) {
2686             # cannot understand from where to where or
2687             # the user did specify the same versions
2688 0         0 $self->run_command_help('clone-modules');
2689 0         0 exit(-1);
2690             }
2691              
2692 4         12 my @modules_to_install = @{ $self->list_modules($src_perl) };
  4         43  
2693              
2694 4 50       62 unless (@modules_to_install) {
2695 0 0       0 print "\nNo modules installed on $src_perl !\n" unless $self->{quiet};
2696 0         0 return;
2697             }
2698              
2699             print "\nInstalling $#modules_to_install modules from $src_perl to $dst_perl ...\n"
2700 4 50       711 unless $self->{quiet};
2701              
2702             # create a new application to 'exec' the 'cpanm'
2703             # with the specified module list
2704              
2705 4         46 my @args = (
2706             qw(--quiet exec --with),
2707             $dst_perl,
2708             'cpanm'
2709             );
2710 4 100       17 push @args, '--notest' if $self->{notest};
2711 4         19 push @args, @modules_to_install;
2712              
2713 4         52 __PACKAGE__->new(@args)->run;
2714             }
2715              
2716             sub format_info_output
2717             {
2718 4     4 0 8 my ($self, $module) = @_;
2719              
2720 4         11 my $out = '';
2721              
2722 4         10 $out .= "Current perl:\n";
2723 4 100       13 if ($self->current_perl) {
2724 3         136 $out .= " Name: " . $self->current_env . "\n";
2725 3         77 $out .= " Path: " . $self->installed_perl_executable($self->current_perl) . "\n";
2726 3         133 $out .= " Config: " . $self->configure_args($self->current_perl) . "\n";
2727             $out .= join('', " Compiled at: ", (map {
2728 3 100       145 / Compiled at (.+)\n/ ? $1 : ()
  300         32323  
2729             } `@{[ $self->installed_perl_executable($self->current_perl) ]} -V`), "\n");
2730             }
2731             else {
2732 1         51 $out .= "Using system perl." . "\n";
2733 1         6 $out .= "Shebang: " . $self->system_perl_shebang . "\n";
2734             }
2735              
2736 4         89 $out .= "\nperlbrew:\n";
2737 4         138 $out .= " version: " . $self->VERSION . "\n";
2738 4         15 $out .= " ENV:\n";
2739 4         13 for(map{"PERLBREW_$_"}qw(ROOT HOME PATH MANPATH)) {
  16         50  
2740 16   50     57 $out .= " $_: " . ($self->env($_)||"") . "\n";
2741             }
2742              
2743 4 100       16 if ($module) {
2744 2         22 my $code = qq{eval "require $module" and do { (my \$f = "$module") =~ s<::>g; \$f .= ".pm"; print "$module\n Location: \$INC{\$f}\n Version: " . ($module->VERSION ? $module->VERSION : "no VERSION specified" ) } or do { print "$module could not be found, is it installed?" } };
2745 2         31 $out .= "\nModule: ".$self->do_capture($self->installed_perl_executable($self->current_perl), "-le", $code);
2746             }
2747              
2748 4         2499 $out;
2749             }
2750              
2751             sub run_command_info {
2752 4     4 0 17 my ($self) = shift;
2753 4         17 print $self->format_info_output(@_);
2754             }
2755              
2756             sub BASHRC_CONTENT() {
2757             return "export PERLBREW_SHELLRC_VERSION=$VERSION\n" .
2758 10 100   10 0 287 (exists $ENV{PERLBREW_ROOT} ? "export PERLBREW_ROOT=$PERLBREW_ROOT\n" : "") . "\n" . <<'RC';
2759              
2760             __perlbrew_reinit() {
2761             if [[ ! -d "$PERLBREW_HOME" ]]; then
2762             mkdir -p "$PERLBREW_HOME"
2763             fi
2764              
2765             [ -f "$PERLBREW_HOME/init" ] && rm "$PERLBREW_HOME/init"
2766             echo '# DO NOT EDIT THIS FILE' > "$PERLBREW_HOME/init"
2767             command perlbrew env $1 | \grep PERLBREW_ >> "$PERLBREW_HOME/init"
2768             . "$PERLBREW_HOME/init"
2769             __perlbrew_set_path
2770             }
2771              
2772             __perlbrew_purify () {
2773             local path patharray outsep
2774             IFS=: read -r${BASH_VERSION+a}${ZSH_VERSION+A} patharray <<< "$1"
2775             for path in "${patharray[@]}" ; do
2776             case "$path" in
2777             (*"$PERLBREW_HOME"*) ;;
2778             (*"$PERLBREW_ROOT"*) ;;
2779             (*) printf '%s' "$outsep$path" ; outsep=: ;;
2780             esac
2781             done
2782             }
2783              
2784             __perlbrew_set_path () {
2785             export MANPATH=${PERLBREW_MANPATH:-}${PERLBREW_MANPATH:+:}$(__perlbrew_purify "$(manpath 2>/dev/null)")
2786             export PATH=${PERLBREW_PATH:-$PERLBREW_ROOT/bin}:$(__perlbrew_purify "$PATH")
2787             hash -r
2788             }
2789              
2790             __perlbrew_set_env() {
2791             local code
2792             code="$($perlbrew_command env $@)" || return $?
2793             eval "$code"
2794             }
2795              
2796             __perlbrew_activate() {
2797             [[ -n $(alias perl 2>/dev/null) ]] && unalias perl 2>/dev/null
2798              
2799             if [[ -n "${PERLBREW_PERL:-}" ]]; then
2800             __perlbrew_set_env "${PERLBREW_PERL:-}${PERLBREW_LIB:+@}$PERLBREW_LIB"
2801             fi
2802              
2803             __perlbrew_set_path
2804             }
2805              
2806             __perlbrew_deactivate() {
2807             __perlbrew_set_env
2808             unset PERLBREW_PERL
2809             unset PERLBREW_LIB
2810             __perlbrew_set_path
2811             }
2812              
2813             perlbrew () {
2814             local exit_status
2815             local short_option
2816             export SHELL
2817              
2818             if [[ $1 == -* ]]; then
2819             short_option=$1
2820             shift
2821             else
2822             short_option=""
2823             fi
2824              
2825             case $1 in
2826             (use)
2827             if [[ -z "$2" ]] ; then
2828             echo -n "Currently using ${PERLBREW_PERL:-system perl}"
2829             [ -n "$PERLBREW_LIB" ] && echo -n "@$PERLBREW_LIB"
2830             echo
2831             else
2832             __perlbrew_set_env "$2" && { __perlbrew_set_path ; true ; }
2833             exit_status="$?"
2834             fi
2835             ;;
2836              
2837             (switch)
2838             if [[ -z "$2" ]] ; then
2839             command perlbrew switch
2840             else
2841             perlbrew use $2 && { __perlbrew_reinit $2 ; true ; }
2842             exit_status=$?
2843             fi
2844             ;;
2845              
2846             (off)
2847             __perlbrew_deactivate
2848             echo "perlbrew is turned off."
2849             ;;
2850              
2851             (switch-off)
2852             __perlbrew_deactivate
2853             __perlbrew_reinit
2854             echo "perlbrew is switched off."
2855             ;;
2856              
2857             (*)
2858             command perlbrew $short_option "$@"
2859             exit_status=$?
2860             ;;
2861             esac
2862             hash -r
2863             return ${exit_status:-0}
2864             }
2865              
2866             [[ -z "${PERLBREW_ROOT:-}" ]] && export PERLBREW_ROOT="$HOME/perl5/perlbrew"
2867             [[ -z "${PERLBREW_HOME:-}" ]] && export PERLBREW_HOME="$HOME/.perlbrew"
2868              
2869             if [[ ! -n "${PERLBREW_SKIP_INIT:-}" ]]; then
2870             if [[ -f "${PERLBREW_HOME:-}/init" ]]; then
2871             . "$PERLBREW_HOME/init"
2872             fi
2873             fi
2874              
2875             if [[ -f "${PERLBREW_ROOT:-}/bin/perlbrew" ]]; then
2876             perlbrew_command="${PERLBREW_ROOT:-}/bin/perlbrew"
2877             else
2878             perlbrew_command="perlbrew"
2879             fi
2880              
2881             __perlbrew_activate
2882              
2883             RC
2884              
2885             }
2886              
2887             sub BASH_COMPLETION_CONTENT() {
2888 5     5 0 32 return <<'COMPLETION';
2889             if [[ -n ${ZSH_VERSION-} ]]; then
2890             autoload -U +X bashcompinit && bashcompinit
2891             fi
2892              
2893             export PERLBREW="command perlbrew"
2894             _perlbrew_compgen()
2895             {
2896             COMPREPLY=( $($PERLBREW compgen $COMP_CWORD ${COMP_WORDS[*]}) )
2897             }
2898             complete -F _perlbrew_compgen perlbrew
2899             COMPLETION
2900             }
2901              
2902             sub PERLBREW_FISH_CONTENT {
2903 5     5 0 91 return "set -x PERLBREW_SHELLRC_VERSION $VERSION\n" . <<'END';
2904              
2905             function __perlbrew_reinit
2906             if not test -d "$PERLBREW_HOME"
2907             mkdir -p "$PERLBREW_HOME"
2908             end
2909              
2910             echo '# DO NOT EDIT THIS FILE' > "$PERLBREW_HOME/init"
2911             command perlbrew env $argv[1] | \grep PERLBREW_ >> "$PERLBREW_HOME/init"
2912             __source_init
2913             __perlbrew_set_path
2914             end
2915              
2916             function __perlbrew_set_path
2917             set -l MANPATH_WITHOUT_PERLBREW (perl -e 'print join ":", grep { index($_, $ENV{PERLBREW_HOME}) < 0 } grep { index($_, $ENV{PERLBREW_ROOT}) < 0 } split/:/,qx(manpath 2> /dev/null);')
2918              
2919             if test -n "$PERLBREW_MANPATH"
2920             set -l PERLBREW_MANPATH $PERLBREW_MANPATH":"
2921             set -x MANPATH {$PERLBREW_MANPATH}{$MANPATH_WITHOUT_PERLBREW}
2922             else
2923             set -x MANPATH $MANPATH_WITHOUT_PERLBREW
2924             end
2925              
2926             set -l PATH_WITHOUT_PERLBREW (eval $perlbrew_command display-pristine-path | perl -pe'y/:/ /')
2927              
2928             # silencing stderr in case there's a non-existent path in $PATH (see GH#446)
2929             if test -n "$PERLBREW_PATH"
2930             set -x PERLBREW_PATH (echo $PERLBREW_PATH | perl -pe 'y/:/ /' )
2931             eval set -x PATH $PERLBREW_PATH $PATH_WITHOUT_PERLBREW 2> /dev/null
2932             else
2933             eval set -x PATH $PERLBREW_ROOT/bin $PATH_WITHOUT_PERLBREW 2> /dev/null
2934             end
2935             end
2936              
2937             function __perlbrew_set_env
2938             set -l code (eval $perlbrew_command env $argv | perl -pe 's/^(export|setenv)/set -xg/; s/=/ /; s/^unset(env)* (.*)/if test -n "\$$2"; set -eg $2; end/; s/$/;/; y/:/ /')
2939              
2940             if test -z "$code"
2941             return 0;
2942             else
2943             eval $code
2944             end
2945             end
2946              
2947             function __perlbrew_activate
2948             functions -e perl
2949              
2950             if test -n "$PERLBREW_PERL"
2951             if test -z "$PERLBREW_LIB"
2952             __perlbrew_set_env $PERLBREW_PERL
2953             else
2954             __perlbrew_set_env $PERLBREW_PERL@$PERLBREW_LIB
2955             end
2956             end
2957              
2958             __perlbrew_set_path
2959             end
2960              
2961             function __perlbrew_deactivate
2962             __perlbrew_set_env
2963             set -x PERLBREW_PERL
2964             set -x PERLBREW_LIB
2965             set -x PERLBREW_PATH
2966             __perlbrew_set_path
2967             end
2968              
2969             function perlbrew
2970              
2971             test -z "$argv"
2972             and echo " Usage: perlbrew [options] [arguments]"
2973             and echo " or: perlbrew help"
2974             and return 1
2975              
2976             switch $argv[1]
2977             case use
2978             if test ( count $argv ) -eq 1
2979             if test -z "$PERLBREW_PERL"
2980             echo "Currently using system perl"
2981             else
2982             echo "Currently using $PERLBREW_PERL"
2983             end
2984             else
2985             __perlbrew_set_env $argv[2]
2986             if test "$status" -eq 0
2987             __perlbrew_set_path
2988             end
2989             end
2990              
2991             case switch
2992             if test ( count $argv ) -eq 1
2993             command perlbrew switch
2994             else
2995             perlbrew use $argv[2]
2996             if test "$status" -eq 0
2997             __perlbrew_reinit $argv[2]
2998             end
2999             end
3000              
3001             case off
3002             __perlbrew_deactivate
3003             echo "perlbrew is turned off."
3004              
3005             case switch-off
3006             __perlbrew_deactivate
3007             __perlbrew_reinit
3008             echo "perlbrew is switched off."
3009              
3010             case '*'
3011             command perlbrew $argv
3012             end
3013             end
3014              
3015             function __source_init
3016             perl -pe 's/^(export|setenv)/set -xg/; s/^unset(env)* (.*)/if test -n "\$$2"; set -eg $2; end/; s/=/ /; s/$/;/;' "$PERLBREW_HOME/init" | source
3017             end
3018              
3019             if test -z "$PERLBREW_ROOT"
3020             set -x PERLBREW_ROOT "$HOME/perl5/perlbrew"
3021             end
3022              
3023             if test -z "$PERLBREW_HOME"
3024             set -x PERLBREW_HOME "$HOME/.perlbrew"
3025             end
3026              
3027             if test -z "$PERLBREW_SKIP_INIT" -a -f "$PERLBREW_HOME/init"
3028             __source_init
3029             end
3030              
3031             set perlbrew_bin_path "$PERLBREW_ROOT/bin"
3032              
3033             if test -f "$perlbrew_bin_path/perlbrew"
3034             set perlbrew_command "$perlbrew_bin_path/perlbrew"
3035             else
3036             set perlbrew_command perlbrew
3037             end
3038              
3039             set -e perlbrew_bin_path
3040              
3041             __perlbrew_activate
3042              
3043             ## autocomplete stuff #############################################
3044              
3045             function __fish_perlbrew_needs_command
3046             set cmd (commandline -opc)
3047             if test (count $cmd) -eq 1 -a $cmd[1] = 'perlbrew'
3048             return 0
3049             end
3050             return 1
3051             end
3052              
3053             function __fish_perlbrew_using_command
3054             set cmd (commandline -opc)
3055             if test (count $cmd) -gt 1
3056             if [ $argv[1] = $cmd[2] ]
3057             return 0
3058             end
3059             end
3060             end
3061              
3062             for com in (perlbrew help | perl -ne'print lc if s/^COMMAND:\s+//')
3063             complete -f -c perlbrew -n '__fish_perlbrew_needs_command' -a $com
3064             end
3065              
3066             for com in switch use;
3067             complete -f -c perlbrew -n "__fish_perlbrew_using_command $com" \
3068             -a '(perlbrew list | perl -pe\'s/\*?\s*(\S+).*/$1/\')'
3069             end
3070              
3071             END
3072             }
3073              
3074             sub CSH_WRAPPER_CONTENT {
3075 5     5 0 130 return <<'WRAPPER';
3076             set perlbrew_exit_status=0
3077              
3078             if ( "$1" =~ -* ) then
3079             set perlbrew_short_option="$1"
3080             shift
3081             else
3082             set perlbrew_short_option=""
3083             endif
3084              
3085             switch ( "$1" )
3086             case use:
3087             if ( $%2 == 0 ) then
3088             if ( $?PERLBREW_PERL == 0 ) then
3089             echo "Currently using system perl"
3090             else
3091             if ( $%PERLBREW_PERL == 0 ) then
3092             echo "Currently using system perl"
3093             else
3094             echo "Currently using $PERLBREW_PERL"
3095             endif
3096             endif
3097             else
3098             set perlbrew_line_count=0
3099             foreach perlbrew_line ( "`\perlbrew env $2:q`" )
3100             eval "$perlbrew_line"
3101             @ perlbrew_line_count++
3102             end
3103             if ( $perlbrew_line_count == 0 ) then
3104             set perlbrew_exit_status=1
3105             else
3106             source "$PERLBREW_ROOT/etc/csh_set_path"
3107             endif
3108             endif
3109             breaksw
3110              
3111             case switch:
3112             if ( $%2 == 0 ) then
3113             \perlbrew switch
3114             else
3115             perlbrew use "$2" && source "$PERLBREW_ROOT/etc/csh_reinit" "$2"
3116             endif
3117             breaksw
3118              
3119             case off:
3120             unsetenv PERLBREW_PERL
3121             foreach perlbrew_line ( "`\perlbrew env`" )
3122             eval "$perlbrew_line"
3123             end
3124             source "$PERLBREW_ROOT/etc/csh_set_path"
3125             echo "perlbrew is turned off."
3126             breaksw
3127              
3128             case switch-off:
3129             unsetenv PERLBREW_PERL
3130             source "$PERLBREW_ROOT/etc/csh_reinit" ''
3131             echo "perlbrew is switched off."
3132             breaksw
3133              
3134             default:
3135             \perlbrew $perlbrew_short_option:q $argv:q
3136             set perlbrew_exit_status=$?
3137             breaksw
3138             endsw
3139             rehash
3140             exit $perlbrew_exit_status
3141             WRAPPER
3142             }
3143              
3144             sub CSH_REINIT_CONTENT {
3145 5     5 0 76 return <<'REINIT';
3146             if ( ! -d "$PERLBREW_HOME" ) then
3147             mkdir -p "$PERLBREW_HOME"
3148             endif
3149              
3150             echo '# DO NOT EDIT THIS FILE' >! "$PERLBREW_HOME/init"
3151             \perlbrew env $1 >> "$PERLBREW_HOME/init"
3152             source "$PERLBREW_HOME/init"
3153             source "$PERLBREW_ROOT/etc/csh_set_path"
3154             REINIT
3155             }
3156              
3157             sub CSH_SET_PATH_CONTENT {
3158 5     5 0 33 return <<'SETPATH';
3159             unalias perl
3160              
3161             if ( $?PERLBREW_PATH == 0 ) then
3162             setenv PERLBREW_PATH "$PERLBREW_ROOT/bin"
3163             endif
3164              
3165             setenv PATH_WITHOUT_PERLBREW `perl -e 'print join ":", grep { index($_, $ENV{PERLBREW_ROOT}) } split/:/,$ENV{PATH};'`
3166             setenv PATH "${PERLBREW_PATH}:${PATH_WITHOUT_PERLBREW}"
3167              
3168             setenv MANPATH_WITHOUT_PERLBREW `perl -e 'print join ":", grep { index($_, $ENV{PERLBREW_ROOT}) } split/:/,qx(manpath 2> /dev/null);'`
3169             if ( $?PERLBREW_MANPATH == 1 ) then
3170             setenv MANPATH ${PERLBREW_MANPATH}:${MANPATH_WITHOUT_PERLBREW}
3171             else
3172             setenv MANPATH ${MANPATH_WITHOUT_PERLBREW}
3173             endif
3174             SETPATH
3175             }
3176              
3177             sub CSHRC_CONTENT {
3178 5     5 0 45 return "setenv PERLBREW_SHELLRC_VERSION $VERSION\n\n" . <<'CSHRC';
3179              
3180             if ( $?PERLBREW_HOME == 0 ) then
3181             setenv PERLBREW_HOME "$HOME/.perlbrew"
3182             endif
3183              
3184             if ( $?PERLBREW_ROOT == 0 ) then
3185             setenv PERLBREW_ROOT "$HOME/perl5/perlbrew"
3186             endif
3187              
3188             if ( $?PERLBREW_SKIP_INIT == 0 ) then
3189             if ( -f "$PERLBREW_HOME/init" ) then
3190             source "$PERLBREW_HOME/init"
3191             endif
3192             endif
3193              
3194             if ( $?PERLBREW_PATH == 0 ) then
3195             setenv PERLBREW_PATH "$PERLBREW_ROOT/bin"
3196             endif
3197              
3198             source "$PERLBREW_ROOT/etc/csh_set_path"
3199             alias perlbrew 'source "$PERLBREW_ROOT/etc/csh_wrapper"'
3200             CSHRC
3201              
3202             }
3203              
3204             sub append_log {
3205 4     4 0 18 my ($self, $message) = @_;
3206 4         7 my $log_handler;
3207             open($log_handler, '>>', $self->{log_file})
3208 4 50       42 or die "Cannot open log file for appending: $!";
3209 4         59 print $log_handler "$message\n";
3210 4         140 close($log_handler);
3211             }
3212              
3213             sub INSTALLATION_FAILURE_MESSAGE {
3214 1     1 0 3 my ($self) = @_;
3215 1         5 return <
3216             Installation process failed. To spot any issues, check
3217              
3218             $self->{log_file}
3219              
3220             If some perl tests failed and you still want to install this distribution anyway,
3221             do:
3222              
3223             (cd $self->{dist_extracted_dir}; make install)
3224              
3225             You might also want to try upgrading patchperl before trying again:
3226              
3227             perlbrew install-patchperl
3228              
3229             Generally, if you need to install a perl distribution known to have minor test
3230             failures, do one of these commands to avoid seeing this message:
3231              
3232             perlbrew --notest install $self->{dist_name}
3233             perlbrew --force install $self->{dist_name}
3234              
3235             FAIL
3236              
3237             }
3238              
3239             1;
3240              
3241             __END__