File Coverage

lib/App/perlbrew.pm
Criterion Covered Total %
statement 910 1339 67.9
branch 337 648 52.0
condition 100 231 43.2
subroutine 104 136 76.4
pod 0 115 0.0
total 1451 2469 58.7


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