File Coverage

lib/App/perlbrew.pm
Criterion Covered Total %
statement 894 1324 67.5
branch 328 632 51.9
condition 99 228 43.4
subroutine 104 136 76.4
pod 0 115 0.0
total 1425 2435 58.5


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