File Coverage

lib/App/perlbrew.pm
Criterion Covered Total %
statement 935 1396 66.9
branch 352 672 52.3
condition 103 234 44.0
subroutine 109 143 76.2
pod 0 120 0.0
total 1499 2565 58.4


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