02.format_perl_version.t000644000765000024 131313614277060 20415 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use English qw( -no_match_vars ); use Test::More; use lib qw(lib); use App::perlbrew; use Test::NoWarnings; my @test_cases = ( { raw => q{5.008008}, parsed => q{5.8.8}, }, { raw => q{5.010001}, parsed => q{5.10.1}, }, { raw => q{5.012002}, parsed => q{5.12.2}, }, { raw => q{5.008}, parsed => q{5.8.0}, }, ); plan tests => scalar @test_cases + 1; { my $app = App::perlbrew->new(); TEST: foreach my $test (@test_cases) { is( $app->format_perl_version( $test->{raw} ), $test->{parsed}, "$test->{raw} -> $test->{parsed}" ); } } failure-command-install-patchperl.t000644000765000024 217613614277060 22615 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use File::Temp qw( tempdir ); use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 ); { no warnings 'redefine'; sub App::perlbrew::http_get { my ($url) = @_; like $url, qr/patchperl$/, "GET patchperl url: $url"; return "Some invalid piece of text"; } } describe "App::perlbrew->install_patchperl" => sub { it "should not produce 'patchperl' in the bin dir, if the downloaded content does not seem to be valid." => sub { my $patchperl = file($perlbrew_root, "bin", "patchperl")->absolute; my $error; my $produced_error = 0; eval { my $app = App::perlbrew->new("install-patchperl", "-q"); $app->run(); } or do { $error = $@; $produced_error = 1; }; ok $produced_error, "generated an error: $error"; ok !(-f $patchperl), "patchperl is *not* installed: $patchperl"; }; }; runtests unless caller; app-perlbrew-path-installation.t000644000765000024 565313614277060 22162 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use File::Temp qw[]; use Test::Spec; use Test::Deep; use App::Perlbrew::Path::Root; use App::Perlbrew::Path::Installation; use App::Perlbrew::Path::Installations; sub looks_like_path;; sub looks_like_perl_installation; sub looks_like_perl_installations; sub arrange_root; sub arrange_installation; describe "App::Perlbrew::Path::Root" => sub { describe "perls()" => sub { context "without parameters" => sub { it "should return Instalations object" => sub { local $ENV{HOME}; my $path = arrange_root->perls; cmp_deeply $path, looks_like_perl_installations ("~/.root/perls"); }; }; context "with one parameter" => sub { it "should return Installation object" => sub { local $ENV{HOME}; my $path = arrange_root->perls ('blead'); cmp_deeply $path, looks_like_perl_installation ("~/.root/perls/blead"); }; }; context "with multiple paramters" => sub { it "should return Path object" => sub { local $ENV{HOME}; my $path = arrange_root->perls ('blead', '.version'); cmp_deeply $path, looks_like_path ("~/.root/perls/blead/.version"); }; } }; }; describe "App::Perlbrew::Path::Installations" => sub { describe "list()" => sub { it "should list known installations" => sub { local $ENV{HOME}; my $root = arrange_root; arrange_installation 'perl-1'; arrange_installation 'perl-2'; my @list = $root->perls->list; cmp_deeply \@list, [ looks_like_perl_installation ("~/.root/perls/perl-1"), looks_like_perl_installation ("~/.root/perls/perl-2"), ]; }; }; }; describe "App::Perlbrew::Path::Installation" => sub { describe "name()" => sub { it "should return installation name" => sub { local $ENV{HOME}; my $installation = arrange_installation ('foo-bar'); cmp_deeply $installation->name, 'foo-bar'; }; it "should provide path to perl" => sub { local $ENV{HOME}; my $perl = arrange_installation ('foo-bar')->perl; cmp_deeply $perl->stringify_with_tilde, '~/.root/perls/foo-bar/bin/perl'; }; it "should provide path to version file" => sub { local $ENV{HOME}; my $file = arrange_installation ('foo-bar')->version_file; cmp_deeply $file->stringify_with_tilde, '~/.root/perls/foo-bar/.version'; }; }; }; runtests unless caller; sub looks_like_path { my ($path, @tests) = @_; my $method = $path =~ m/^~/ ? 'stringify_with_tilde' : 'stringify' ; all ( methods ($method => $path), Isa ('App::Perlbrew::Path'), @tests, ); } sub looks_like_perl_installation { looks_like_path (@_, Isa ('App::Perlbrew::Path::Installation')); } sub looks_like_perl_installations { looks_like_path (@_, Isa ('App::Perlbrew::Path::Installations')); } sub arrange_root { $ENV{HOME} ||= File::Temp::tempdir (CLEANUP => 1); App::Perlbrew::Path::Root->new ($ENV{HOME}, '.root')->mkpath; } sub arrange_installation { my ($name) = @_; my $root = arrange_root; $root->perls ($name)->mkpath; } command-compgen.t000644000765000024 476713614277060 17202 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; use Test::Output qw( stdout_from ); $ENV{PERLBREW_DEBUG_COMPLETION} = 0; my @perls = qw( perl-5.12.3 perl-5.12.4 perl-5.14.1 perl-5.14.2 ); mock_perlbrew_install($_) for @perls; { no warnings 'redefine'; sub App::perlbrew::current_perl { "perl-5.12.3" } } describe "compgen command," => sub { describe "when there is no args", sub { it "displays a list of subcommands", sub { my $app = App::perlbrew->new("compgen"); my $out = stdout_from { $app->run; }; my @subcommands = sort split ' ', $out; is join(' ', @subcommands), join(' ', sort $app->commands()); }; }; describe "when there is a part of a subcommand", sub { it "displays a list of l*", sub { my $part = "l"; my $app = App::perlbrew->new("compgen", 1, 'perlbrew', $part); my $out = stdout_from { $app->run; }; my @subcommands = sort split ' ', $out; is join(' ', @subcommands), join(' ', sort grep { /\A \Q$part\E /xms } $app->commands()); }; it "'versio[tab]' is completed as 'version'", sub { my $part = "versio"; my $app = App::perlbrew->new("compgen", 1, 'perlbrew', $part); my $out = stdout_from { $app->run; }; my @subcommands = sort split ' ', $out; is join(' ', @subcommands), join(' ', 'version'); }; }; foreach my $use(qw(use switch)) { describe "given '$use' subcommand", sub { it "'use [tab]' suggests a list of installed perls", sub { my $app = App::perlbrew->new( "compgen", 2, 'perlbrew', 'use'); my $out = stdout_from { $app->run; }; my @subcommands = sort split ' ', $out; is join(' ', @subcommands), join(' ', sort @perls); }; it "'use 5.12 [tab]' suggests perls with /5\\.12/", sub { my $app = App::perlbrew->new( "compgen", 2, 'perlbrew', 'use', '5.12'); my $out = stdout_from { $app->run; }; my @subcommands = sort split ' ', $out; is join(' ', @subcommands), join(' ', sort( qw(perl-5.12.3 perl-5.12.4) )); }; }; } }; runtests unless caller; CONTRIBUTING.md000644000765000024 173613614277060 15730 0ustar00gugodstaff000000000000App-perlbrew-0.88Hi Hackers, perlbrew is open for anyone who are willing to contribute. Here's what you do to get your work released: - Fork the repository on github - Modify `lib/App/perlbrew.pm` or `script/perlbrew` if necessary. - Add tests so others do not break your feature. - Send a pull request to @gugod and make an offer that he cannot reject (optional :-) Notice that the "master" branch is a stable branch, while the "develop" branch is the default target for pull requests. The master branch should only be moved forward on CPAN releases and there should also be a corresponding git tag for each release, which is the part only @gugod has to worry about. It is suggested, but not required, that you create your own topic branch first and work on the feature, this way it makes it a little bit easier when there are conflicts. Last, DO NOT edit the `./perlbrew` file directly, it is a standalone executable built with `dev-bin/build.sh`. Happy hacking! Sincerely, Kang-min Liu, aka @gugod command-help.t000644000765000024 267313614277060 16474 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; my $bin_perlbrew = file(__FILE__)->dirname->dirname->child("script")->child("perlbrew"); my $perl = $^X; # # Doing `App::perlbrew->new("help")->run` will make this test program exit(), # that's why we use backtick to test. # describe "`perlbrew`" => sub { it "should print some nice message and instruct user to read help for individual commands" => sub { my $out = `$perl -Ilib $bin_perlbrew help`; like $out, qr/perlbrew help /si; }; }; describe "`perlbrew help`" => sub { it "should instruct user to read help for individual commands." => sub { my $out = `$perl -Ilib $bin_perlbrew help`; like $out, qr/perlbrew help /si; }; it "should be the same as doing `perlbrew -h` or `perlbrew --help`" => sub { my $out1 = `$perl -Ilib $bin_perlbrew help`; my $out2 = `$perl -Ilib $bin_perlbrew -h`; my $out3 = `$perl -Ilib $bin_perlbrew --help`; is $out1, $out2; is $out1, $out3; }; }; describe "`help install`" => sub { it "should show the options for install command" => sub { my $out = `$perl -Ilib $bin_perlbrew help install`; like $out, qr/^Options for "install" command:/msi; like $out, qr/--force/si; like $out, qr/--notest/si; }; }; runtests unless caller; 10.resolve.t000644000765000024 404713614277060 16023 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; use Test::Exception; mock_perlbrew_install("perl-5.8.9"); mock_perlbrew_install("perl-5.14.0"); mock_perlbrew_install("perl-5.8.9", "--as" => "5.8.9"); mock_perlbrew_install("perl-5.14.0", "--as" => "perl-shiny", "perl-5.14.0"); { no warnings 'redefine'; sub App::perlbrew::current_perl { "perl-5.14.0" } } ## spec describe "App::perlbrew->resolve_installation_name" => sub { my $app; before each => sub { $app = App::perlbrew->new; }; it "takes exactly one argument, which means the `shortname` that needs to be resolved to a `longname`", sub { ok $app->resolve_installation_name("5.8.9"); dies_ok { $app->resolve_installation_name; # no args }; }; it "returns the same value as the argument if there is an installation with exactly the same name", sub { is $app->resolve_installation_name("5.8.9"), "5.8.9"; is $app->resolve_installation_name("perl-5.8.9"), "perl-5.8.9"; is $app->resolve_installation_name("perl-5.14.0"), "perl-5.14.0"; }; it "returns `perl-\$shortname` if that happens to be a proper installation name.", sub { is $app->resolve_installation_name("5.14.0"), "perl-5.14.0"; is $app->resolve_installation_name("shiny"), "perl-shiny"; }; it "returns undef if no proper installation can be found", sub { is $app->resolve_installation_name("nihao"), undef; }; describe 'with lib names' => sub { it 'returns both perl version and libnames' => sub { my ($v, $l) = $app->resolve_installation_name('perl-5.14.0@soya'); is $v, "perl-5.14.0"; is $l, "soya"; }; it 'returns current perl version when only a libname is given' => sub { my ($v, $l) = $app->resolve_installation_name('@soya'); is $v, $app->current_perl; is $l, "soya"; }; }; }; runtests unless caller; 18.release-detail-perl-local.t000644000765000024 125613614277060 21263 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; my $app = App::perlbrew->new(); $app->cpan_mirror("http://www.cpan.org"); my $rd = { type => "perl", "version" => "5.18.2" }; my ($error, undef) = $app->release_detail_perl_local("perl-5.18.2", $rd); ok !$error; ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{tarball_url}, "http://www.cpan.org/authors/id/R/RJ/RJBS/perl-5.18.2.tar.bz2"; is $rd->{tarball_name}, "perl-5.18.2.tar.bz2"; done_testing; command-alias.t000644000765000024 207213614277060 16626 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl #!/usr/bin/env perl use strict; use warnings; BEGIN { $ENV{SHELL} = "/bin/bash" } use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; use Test::Output; use Config; mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_lib_create('perl-5.14.1@nobita'); describe "alias command," => sub { before each => sub { delete $ENV{PERL_MB_OPT}; delete $ENV{PERL_MM_OPT}; delete $ENV{PERL_LOCAL_LIB_ROOT}; delete $ENV{PERLBREW_LIB}; delete $ENV{PERL5LIB}; }; describe "when invoked with unknown action name,", sub { it "should display usage message" => sub { my $x = "correcthorsebatterystaple"; my $app = App::perlbrew->new("alias", $x); stderr_like { eval { $app->run; 1; } or do { print STDERR $@; }; } qr/ERROR: Unrecognized action: `$x`/; } }; }; runtests unless caller; META.yml000644000765000024 274413614277060 14750 0ustar00gugodstaff000000000000App-perlbrew-0.88--- abstract: 'Manage perl installations in your C<$HOME>' author: - 'Kang-min Liu C<< >>' build_requires: File::Which: '1.21' IO::All: '0.51' Path::Class: '0.33' Test::Exception: '0.32' Test::More: '1.001002' Test::NoWarnings: '1.04' Test::Output: '1.03' Test::Simple: '1.001002' Test::Spec: '0.47' Test::TempDir::Tiny: '0.016' configure_requires: Module::Build::Tiny: '0.034' dynamic_config: 0 generated_by: 'App::ModuleBuildTiny version 0.027, CPAN::Meta::Converter version 2.150010' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: App-perlbrew provides: App::Perlbrew::Path: file: lib/App/Perlbrew/Path.pm App::Perlbrew::Path::Installation: file: lib/App/Perlbrew/Path/Installation.pm App::Perlbrew::Path::Installations: file: lib/App/Perlbrew/Path/Installations.pm App::Perlbrew::Path::Root: file: lib/App/Perlbrew/Path/Root.pm App::Perlbrew::Util: file: lib/App/Perlbrew/Util.pm App::perlbrew: file: lib/App/perlbrew.pm version: '0.88' requires: CPAN::Perl::Releases: '5.20191220' Capture::Tiny: '0.36' Devel::PatchPerl: '1.80' ExtUtils::MakeMaker: '7.22' File::Temp: '0.2304' JSON::PP: '0' Pod::Parser: '1.63' Pod::Usage: '1.68' local::lib: '2.000014' resources: repository: https://github.com/gugod/App-perlbrew.git version: '0.88' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_spdx_expression: MIT x_static_install: '1' http-ua-detect-non-curl.t000644000765000024 116113614277060 20502 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin qw($Bin); BEGIN { $ENV{PATH} = "$Bin/fake-bin:" . $ENV{PATH}; } use File::Which qw(which); use App::perlbrew; use Test::More; chmod 0755, "$Bin/fake-bin/curl"; diag "PATH=$ENV{PATH}"; my $curl_path = which("curl"); diag "curl = $curl_path"; is $curl_path, "$Bin/fake-bin/curl"; my $expected_ua; if (which("wget")) { $expected_ua = "wget"; } elsif (which("fetch")) { $expected_ua = "fetch"; } if ($expected_ua) { my $detected_ua = App::perlbrew::http_user_agent_program(); is $detected_ua, $expected_ua, "UA: $detected_ua"; } done_testing; 12.destdir.t000644000765000024 614513614277060 16005 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use Capture::Tiny qw/capture/; use IO::All; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; my $DESTDIR = tempdir( CLEANUP => 1 ); use Test::More; ## setup App::Perlbrew::Path ->new ($ENV{PERLBREW_ROOT}) ->rmpath ; ## mock no warnings 'redefine'; sub App::perlbrew::do_system { my ($self, $cmd) = @_; if ($cmd =~ /sitelib/) { print "sitelib='$ENV{PERLBREW_ROOT}/perls/perl-5.14.2/lib/site_perl/5.14.2';\n"; print "installprefix='$ENV{PERLBREW_ROOT}/perls/perl-5.14.2';\n"; print "installstyle='lib';\n"; return 1; } elsif ($cmd =~ /Configure/) { # pretend to succeed return 1; } else { # fail to run $? = 1<<8; $! = "Could not run '$cmd'"; return 0; } } sub App::perlbrew::do_install_release { my ($self, $dist) = @_; my ($dist_name, $dist_version) = $dist =~ m/^(.*)-([\d.]+(?:-RC\d+)?)$/; my $name = $dist; $name = $self->{as} if $self->{as}; my $root = App::Perlbrew::Path->new ($DESTDIR, $ENV{PERLBREW_ROOT}); my $installation_dir = $root->child("perls", $name); $installation_dir->mkpath; $root->child("perls", $name, "bin")->mkpath; my $perl = $root->child("perls", $name, "bin")->child("perl"); io($perl)->print("#!/bin/sh\nperl \"\$@\";\n"); chmod 0755, $perl; # fake the install $self->do_install_this("/tmp/fake-src/perl-5.14.2", $dist_version, $dist); } use warnings; ## main note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; note "DESTDIR set to $DESTDIR"; subtest "No perls yet installed" => sub { my $app = App::perlbrew->new; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 0, "no perls installed"; }; subtest "--destdir option can be set" => sub { my $app = App::perlbrew->new('install', 'perl-5.14.2', '--destdir=/tmp/foo' ); is join(' ', $app->args), join(' ', qw(install perl-5.14.2)), "post-option args correct"; is $app->{destdir}, '/tmp/foo', '--destdir set as expected'; }; subtest "mock installing" => sub { my $sitefile = File::Temp->new; print $sitefile "use strict;\n"; close $sitefile; my $app = App::perlbrew->new('install', 'perl-5.14.2', "--destdir=$DESTDIR", "--sitecustomize=$sitefile" ); my ($output,$error) = capture { $app->run }; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 0, "found 0 installed perl (as it's installed in DESTDIR)"; my $root = App::Perlbrew::Path->new ($DESTDIR, $ENV{PERLBREW_ROOT}); my $perldir = $root->child("perls", "perl-5.14.2"); my $installedsite = $perldir->child('lib', 'site_perl', '5.14.2', 'sitecustomize.pl'); ok( -f $installedsite, "sitecustomize.pl installed in DESTDIR" ); my $guts = do { local (@ARGV, $/) = $installedsite; <> }; is( $guts, "use strict;\n", "sitecustomize.pl contents correct in DESTDIR" ); }; done_testing; # vim: ts=4 sts=4 sw=4 et: Path.pm000644000765000024 375113614277060 20000 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/App/Perlbrew use strict; use warnings; package App::Perlbrew::Path; require File::Basename; require File::Glob; require File::Path; use overload ( '""' => \& stringify, fallback => 1, ); sub _joinpath { for my $entry(@_) { no warnings 'uninitialized'; die 'Received an undefined entry as a parameter (all parameters are: '. join(', ', @_). ')' unless (defined($entry)); } return join "/", @_; } sub _child { my ($self, $package, @path) = @_; $package->new ($self->{path}, @path); } sub _children { my ($self, $package) = @_; return map $package->new ($_), File::Glob::bsd_glob ($self->child ("*")) ; } sub new { my ($class, @path) = @_; bless { path => _joinpath (@path) }, $class; } sub basename { my ($self, $suffix) = @_; return scalar File::Basename::fileparse ($self, ($suffix) x!! defined $suffix); } sub child { my ($self, @path) = @_; return $self->_child (__PACKAGE__, @path); } sub children { my ($self) = @_; return $self->_children (__PACKAGE__); } sub dirname { my ($self) = @_; return App::Perlbrew::Path->new (File::Basename::dirname ($self)); } sub mkpath { my ($self) = @_; File::Path::mkpath ([$self->stringify], 0, 0777); return $self; } sub readlink { my ($self) = @_; my $link = readlink $self->stringify; $link = __PACKAGE__->new ($link) if defined $link; return $link; } sub rmpath { my ($self) = @_; File::Path::rmtree([$self->stringify], 0, 0); return $self; } sub stringify { my ($self) = @_; return $self->{path}; } sub stringify_with_tilde { my ($self) = @_; my $path = $self->stringify; my $home = $ENV{HOME}; $path =~ s!\Q$home/\E!~/! if $home; return $path; } sub symlink { my ($self, $destination, $force) = @_; $destination = App::Perlbrew::Path->new ($destination) unless ref $destination; CORE::unlink $destination if $force && (-e $destination || -l $destination); $destination if CORE::symlink $self, $destination; } sub unlink { my ($self) = @_; CORE::unlink ($self); } 1; 01.options.t000644000765000024 204613614277060 16034 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use Test::More tests => 12; use App::perlbrew; my $app = App::perlbrew->new('install', '-n', 'perl-5.12.1', '-Dusethreads', '-DDEBUGGING', '-Uusemymalloc', '-Accflags'); note explain($app) if (main->can('note') && main->can('explain')); is join(' ', $app->args), join(' ', qw(install perl-5.12.1)); is_deeply $app->{D}, [qw(usethreads DEBUGGING)], '-D'; is_deeply $app->{U}, [qw(usemymalloc)], '-U'; is_deeply $app->{A}, [qw(ccflags)], '-A'; ok !$app->{quiet}, 'not quiet'; ok $app->{notest}, 'notest'; $app = App::perlbrew->new('install', '--quiet', 'perl-5.12.1', '-D', 'usethreads', '-D=DEBUGGING', '-U', 'usemymalloc', '-A', 'ccflags'); note explain($app) if (main->can('note') && main->can('explain')); is join(' ', $app->args), join(' ', qw(install perl-5.12.1)); is_deeply $app->{D}, [qw(usethreads DEBUGGING)], '-D'; is_deeply $app->{U}, [qw(usemymalloc)], '-U'; is_deeply $app->{A}, [qw(ccflags)], '-A'; ok $app->{quiet}, 'quiet'; ok !$app->{notest}, 'notest'; Root.pm000644000765000024 102713614277060 20715 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/App/Perlbrew/Path use strict; use warnings; package App::Perlbrew::Path::Root; require App::Perlbrew::Path; require App::Perlbrew::Path::Installations; our @ISA = qw( App::Perlbrew::Path ); sub bin { shift->child (bin => @_); } sub build { shift->child (build => @_); } sub dists { shift->child (dists => @_); } sub etc { shift->child (etc => @_); } sub perls { my ($self, @params) = @_; my $return = $self->_child ('App::Perlbrew::Path::Installations', 'perls'); $return = $return->child (@params) if @params; return $return; } 1; unit-files-are-the-same.t000644000765000024 75613614277060 20435 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use Test::More; use App::perlbrew; use FindBin qw($RealBin); my @test_files = (<$RealBin/*.t>)[0..9]; for my $i (0..$#test_files) { my $t = $test_files[$i]; my $u = $test_files[$i - 1]; my $should_be_same = App::perlbrew::files_are_the_same($t, $t); my $should_not_be_same = App::perlbrew::files_are_the_same($t, $u); ok ($^O eq 'MSWin32' xor $should_be_same); # should return false on win32 ok !$should_not_be_same; } done_testing; command-install-patchperl.t000644000765000024 165513614277060 21171 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use File::Temp qw( tempdir ); use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 ); { no warnings 'redefine'; sub App::perlbrew::http_get { my ($url) = @_; like $url, qr/patchperl$/, "GET patchperl url: $url"; return "#!/usr/bin/env perl\n# The content of patchperl"; } } describe "App::perlbrew->install_patchperl" => sub { it "should produce 'patchperl' in the bin dir" => sub { my $app = App::perlbrew->new("install-patchperl", "-q"); $app->run(); my $patchperl = App::Perlbrew::Path->new ($perlbrew_root, "bin", "patchperl"); ok -f $patchperl, "patchperl is produced. $patchperl"; ok -x $patchperl, "patchperl should be an executable."; }; }; runtests unless caller; do_system.t000644000765000024 104613614277060 16127 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::More tests => 2; # test that 'do_system' wraps 'system' correctly our @system; BEGIN { *CORE::GLOBAL::system = sub { @system = @_; }; } use App::perlbrew; # don't actually run() it, we just want to call do_system my $app = App::perlbrew->new('list'); $app->do_system(qw(perl -E), 'say 42'); is_deeply \@system, [qw(perl -E), 'say 42'], 'passed all arguments to system()'; $app->do_system("perl -e 'say 42'"); is_deeply \@system, ["perl -e 'say 42'"], 'passed single string to system()'; 14.perl_version_parsing.t000644000765000024 761013614277060 20601 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; # # This test checks if the sorting order of parsed version is the same as # the order of @versions array defined below. # my @versions = qw( 5.003_07 5.004 5.004_01 5.004_02 5.004_03 5.004_04 5.004_05 5.005 5.005_01 5.005_02 5.005_03 5.005_04 5.6.0 5.6.1-TRIAL1 5.6.1-TRIAL2 5.6.1-TRIAL3 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.7.3 5.8.0 5.8.1 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.10.0-RC1 5.10.0-RC2 5.10.0 5.10.1 5.11.0 5.11.1 5.11.2 5.11.3 5.11.4 5.11.5 5.12.0 5.12.1-RC1 5.12.1-RC2 5.12.1 5.12.2-RC1 5.12.2 5.12.3 5.12.4-RC1 5.12.4-RC2 5.12.4 5.13.0 5.13.1 5.13.2 5.13.3 5.13.4 5.13.5 5.13.6 5.13.7 5.13.8 5.13.9 5.13.10 5.13.11 5.14.0-RC1 5.14.0-RC2 5.14.0-RC3 5.14.0 5.14.1-RC1 5.14.1 5.14.2-RC1 5.14.2 5.14.3-RC1 5.14.3-RC2 5.14.3 5.15.0 5.15.1 5.15.2 5.15.3 5.15.4 5.15.5 5.15.6 5.15.7 5.15.8 5.15.9 5.16.0-RC0 5.16.0-RC1 5.16.0-RC2 5.16.0 5.16.1-RC1 5.16.1 5.16.2-RC1 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 ); use Test::More; subtest "perl_version_to_integer" => sub { plan tests => (@versions - 1); my @versions_i = map { App::perlbrew::perl_version_to_integer($_) } @versions; for my $i (0 .. $#versions_i-1) { ok( $versions_i[$i] < $versions_i[$i+1], "$versions[$i] < $versions[$i+1]"); } }; subtest "comparable_perl_version" => sub { plan tests => 0+@versions; for my $v (@versions) { my $n = App::perlbrew->comparable_perl_version($v); like($n, qr/\-? [0-9]+/x, "can build comparable version from: $v"); } }; done_testing; 06.installed_perls.t000644000765000024 104313614277060 17526 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use lib qw(lib); use Test::More; use App::perlbrew; my $app = App::perlbrew->new(); my @perls = $app->installed_perls; unless(@perls) { plan skip_all => "No perl installation under PERLBREW_ROOT"; exit; } for my $perl (@perls) { is ref($perl), 'HASH'; ok defined $perl->{name}, "Name: $perl->{name}"; ok defined $perl->{version}, "Version: $perl->{version}"; ok defined $perl->{is_current}, "Current?: " . ($perl->{is_current} ? "true" : "false"); } done_testing; installation3.t000644000765000024 162713614277060 16712 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; BEGIN { delete $ENV{PERLBREW_LIB}; } use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; { no warnings 'redefine'; sub App::perlbrew::available_perls { return map { "perl-$_" } qw<5.8.9 5.17.7 5.16.2 5.14.3 5.12.5 5.10.1>; } sub App::perlbrew::switch_to { shift->current_perl(shift); } } plan tests => 3; { my $app = App::perlbrew->new("install", "--switch", "perl-stable"); $app->run; my @installed = $app->installed_perls; is 0+@installed, 1, "install perl-stable installs one perl"; is $installed[0]{name}, "perl-5.16.2", "install perl-stable installs correct perl"; ok $installed[0]{is_current}, "install --switch automatically switches to the installed perl" or diag explain $installed[0]; } done_testing; current_perl.t000644000765000024 250113614277060 16622 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::Spec; mock_perlbrew_install("perl-5.12.3"); mock_perlbrew_install("perl-5.12.4"); mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_install("perl-5.14.2"); describe "current perl" => sub { it "is decided from env var PERLBREW_PERL" => sub { for my $v (qw(perl-5.12.3 perl-5.12.3 perl-5.14.1 perl-5.14.2)) { local $ENV{PERLBREW_PERL} = $v; my $app = App::perlbrew->new; is $app->current_perl, $v; } }; it "can be decided from object attribute, which overrides env var." => sub { local $ENV{PERLBREW_PERL} = "perl-5.12.3"; for my $v (qw(perl-5.12.3 perl-5.12.3 perl-5.14.1 perl-5.14.2)) { my $app = App::perlbrew->new; $app->{current_perl} = $v; is $app->current_perl, $v; } }; it "can be set with current_perl method." => sub { local $ENV{PERLBREW_PERL} = "perl-5.12.3"; for my $v (qw(perl-5.12.3 perl-5.12.3 perl-5.14.1 perl-5.14.2)) { my $app = App::perlbrew->new; is $app->current_perl, "perl-5.12.3"; $app->current_perl($v); is $app->current_perl, $v; } }; }; runtests unless caller; 05.get_current_perl.t000644000765000024 231313614277060 17705 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Output; mock_perlbrew_install("perl-5.12.3"); mock_perlbrew_install("perl-5.12.4"); mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_install("perl-5.14.2"); subtest "perlbrew version" => sub { my $version = $App::perlbrew::VERSION; stdout_like( sub { my $app = App::perlbrew->new("version"); $app->run; } => qr{(?:\./)?\Qt/05.get_current_perl.t - App::perlbrew/$version\E\n} ); }; subtest "Current perl is decided from environment variable PERLBREW_PERL" => sub { for my $v (qw(perl-5.12.3 perl-5.12.3 perl-5.14.1 perl-5.14.2)) { local $ENV{PERLBREW_PERL} = $v; my $app = App::perlbrew->new; is $app->current_perl, $v; } }; subtest "Current perl can be decided from object attribute, which overrides env var." => sub { local $ENV{PERLBREW_PERL} = "perl-5.12.3"; for my $v (qw(perl-5.12.3 perl-5.12.3 perl-5.14.1 perl-5.14.2)) { my $app = App::perlbrew->new; $app->{current_perl} = $v; is $app->current_perl, $v; } }; done_testing; installation.t000644000765000024 272513614277060 16627 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Exception; ## main note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; { my $app = App::perlbrew->new; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 0; } { my $app = App::perlbrew->new("install", "perl-5.14.0"); $app->run; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 1; is $installed[0]->{name}, "perl-5.14.0"; dies_ok { my $app = App::perlbrew->new("install", "perl-5.14.0"); $app->run; } "should die when doing install with existing distribution name."; } subtest "App::perlbrew#is_installed method." => sub { my $app = App::perlbrew->new; ok $app->can("is_installed"); ok $app->is_installed("perl-5.14.0"); ok !$app->is_installed("perl-5.13.0"); }; subtest "do not clobber exitsing user-specified name." => sub { my $app = App::perlbrew->new("install", "perl-5.14.0", "--as", "the-dude"); $app->run; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 2; ok grep { $_->{name} eq 'the-dude' } $app->installed_perls; dies_ok { my $app = App::perlbrew->new("install", "perl-5.14.0", "--as", "the-dude"); $app->run; } "should die when doing install with existing user-specified name."; }; done_testing; command-env.t000644000765000024 702313614277060 16326 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; BEGIN { $ENV{SHELL} = "/bin/bash" } use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; use Test::Output; use Config; mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_lib_create('perl-5.14.1@nobita'); describe "env command," => sub { before each => sub { delete $ENV{PERL_MB_OPT}; delete $ENV{PERL_MM_OPT}; delete $ENV{PERL_LOCAL_LIB_ROOT}; delete $ENV{PERLBREW_LIB}; delete $ENV{PERL5LIB}; delete $ENV{PERLBREW_LIB_PREFIX}; }; describe "when invoked with a perl installation name,", sub { it "displays environment variables that should be set to use the given perl." => sub { my $app = App::perlbrew->new("env", "perl-5.14.1"); stdout_is { $app->run; } <<"OUT"; export PERLBREW_MANPATH="$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/man" export PERLBREW_PATH="$App::perlbrew::PERLBREW_ROOT/bin:$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/bin" export PERLBREW_PERL="perl-5.14.1" export PERLBREW_ROOT="$App::perlbrew::PERLBREW_ROOT" export PERLBREW_VERSION="$App::perlbrew::VERSION" OUT }; }; describe "when invoked with a perl installation name with lib name,", sub { it "displays local::lib-related environment variables that should be set to use the given perl." => sub { note 'perlbrew env perl-5.14.1@nobita'; my $PERL5LIB_maybe = $ENV{PERL5LIB} ? ":\$PERL5LIB" : ""; my $app = App::perlbrew->new("env", 'perl-5.14.1@nobita'); my $lib_dir = "$App::perlbrew::PERLBREW_HOME/libs/perl-5.14.1\@nobita"; stdout_is { $app->run; } <<"OUT"; export PERL5LIB="$lib_dir/lib/perl5${PERL5LIB_maybe}" export PERLBREW_LIB="nobita" export PERLBREW_MANPATH="$lib_dir/man:$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/man" export PERLBREW_PATH="$lib_dir/bin:$App::perlbrew::PERLBREW_ROOT/bin:$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/bin" export PERLBREW_PERL="perl-5.14.1" export PERLBREW_ROOT="$App::perlbrew::PERLBREW_ROOT" export PERLBREW_VERSION="$App::perlbrew::VERSION" export PERL_LOCAL_LIB_ROOT="$lib_dir" export PERL_MB_OPT="--install_base "$lib_dir"" export PERL_MM_OPT="INSTALL_BASE=$lib_dir" OUT } }; describe "when invoked with a perl installation name with lib name and PERLBREW_LIB_PREFIX set,", sub { it "displays PERL5LIB with PERLBREW_LIB_PREFIX value first." => sub { note 'perlbrew env perl-5.14.1@nobita'; $ENV{PERLBREW_LIB_PREFIX} = 'perlbrew_lib_prefix'; my $PERL5LIB_maybe = $ENV{PERL5LIB} ? ":\$PERL5LIB" : ""; my $app = App::perlbrew->new("env", 'perl-5.14.1@nobita'); my $lib_dir = "$App::perlbrew::PERLBREW_HOME/libs/perl-5.14.1\@nobita"; stdout_is { $app->run; } <<"OUT"; export PERL5LIB="$ENV{PERLBREW_LIB_PREFIX}:$lib_dir/lib/perl5${PERL5LIB_maybe}" export PERLBREW_LIB="nobita" export PERLBREW_MANPATH="$lib_dir/man:$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/man" export PERLBREW_PATH="$lib_dir/bin:$App::perlbrew::PERLBREW_ROOT/bin:$App::perlbrew::PERLBREW_ROOT/perls/perl-5.14.1/bin" export PERLBREW_PERL="perl-5.14.1" export PERLBREW_ROOT="$App::perlbrew::PERLBREW_ROOT" export PERLBREW_VERSION="$App::perlbrew::VERSION" export PERL_LOCAL_LIB_ROOT="$lib_dir" export PERL_MB_OPT="--install_base "$lib_dir"" export PERL_MM_OPT="INSTALL_BASE=$lib_dir" OUT } } }; runtests unless caller; 15.no-reuse-build-dir.t000644000765000024 154013614277060 17752 0ustar00gugodstaff000000000000App-perlbrew-0.88/tuse strict; use warnings; use Test::More tests => 6; use File::Basename qw(basename); use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; my $pb = new_ok('App::perlbrew'); my $test_dir = App::Perlbrew::Path->new ($pb->root, qw/build test/); my $test_file = App::Perlbrew::Path->new ( $test_dir, 3 ); $test_dir->mkpath; open my $out, '>', $test_file or die "Couldn't create $test_file: $!"; ok -e $test_file, 'Test file 3 created'; my $extracted_dir = $pb->do_extract_tarball( App::Perlbrew::Path->new ($FindBin::Bin, 'test.tar.gz') ); diag $extracted_dir; is $extracted_dir->basename => 'test', 'Test tarball extracted as expected'; ok !-e $test_file, 'Test file 3 was unlinked by tar'; ok -e App::Perlbrew::Path->new ( $extracted_dir, $_ ), "Test file $_ exists" for 1..2; Build.PL000644000765000024 16613614277060 14747 0ustar00gugodstaff000000000000App-perlbrew-0.88# This Build.PL for App-perlbrew was generated by mbtiny 0.027. use 5.006; use Module::Build::Tiny 0.034; Build_PL(); http-program-control.t000644000765000024 106413614277060 20223 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Exception; for my $prog (qw(curl wget fetch)) { $App::perlbrew::HTTP_USER_AGENT_PROGRAM = $prog; is App::perlbrew::http_user_agent_program(), $prog, "UA Program can be set to: $prog"; } $App::perlbrew::HTTP_USER_AGENT_PROGRAM = "something-that-is-not-recognized"; dies_ok { App::perlbrew::http_user_agent_program(); } "should die when asked to use unrecognized http UA program"; done_testing; command-display-rc.t000644000765000024 117713614277060 17611 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use File::Temp qw( tempdir ); $ENV{PERLBREW_ROOT} = my $perlbrew_root = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_HOME} = my $perlbrew_home = tempdir( CLEANUP => 1 ); use App::perlbrew; describe "App::perlbrew" => sub { my $app; before each => sub { $app = App::perlbrew->new; }; it "should be able to run 'display-bashrc' command" => sub { ok $app->can("run_command_display_bashrc"); }; it "should be able to run 'display-cshrc' command" => sub { ok $app->can("run_command_display_cshrc"); }; }; runtests unless caller; command-install-cpanm.t000644000765000024 157113614277060 20302 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use File::Temp qw( tempdir ); use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 ); { no warnings 'redefine'; sub App::perlbrew::http_get { my ($url) = @_; like $url, qr/cpanm$/, "GET cpanm url: $url"; return "#!/usr/bin/env perl\n# The content of cpanm"; } } describe "App::perlbrew->install_cpanm" => sub { it "should produce 'cpanm' in the bin dir" => sub { my $app = App::perlbrew->new("install-cpanm", "-q"); $app->run(); my $cpanm = App::Perlbrew::Path->new ($perlbrew_root, "bin", "cpanm"); ok -f $cpanm, "cpanm is produced. $cpanm"; ok -x $cpanm, "cpanm should be an executable."; }; }; runtests unless caller; MANIFEST000644000765000024 330313614277060 14620 0ustar00gugodstaff000000000000App-perlbrew-0.88.circleci/config.yml .perlcriticrc Build.PL CONTRIBUTING.md Changes LICENSE MANIFEST META.json META.yml README README.md cpanfile doc/MIT-LICENSE doc/PERL-LICENSE lib/App/Perlbrew/Path.pm lib/App/Perlbrew/Path/Installation.pm lib/App/Perlbrew/Path/Installations.pm lib/App/Perlbrew/Path/Root.pm lib/App/Perlbrew/Util.pm lib/App/perlbrew.pm metamerge.json script/perlbrew t/00.load.t t/01.options.t t/02.format_perl_version.t t/03.test_get_available_versions.t t/04.find_available_perls.t t/05.get_current_perl.t t/06.installed_perls.t t/07.argv.t t/08.error_available.t t/08.error_install.t t/08.error_install_blead.t t/08.error_install_cpanm.t t/09.exit_status.t t/10.resolve.t t/11.editdist.t t/11.root_from_arg.t t/12.destdir.t t/12.sitecustomize.t t/13.perl_release.t t/14.perl_version_parsing.t t/15.no-reuse-build-dir.t t/16.release-detail.t t/17.release-detail-cperl-local.t t/17.release-detail-cperl-remote.t t/18.release-detail-perl-local.t t/18.release-detail-perl-remote.t t/app-perlbrew-path-installation.t t/app-perlbrew-path.t t/bashrc_content.t t/builddir.t t/command-alias.t t/command-available.t t/command-compgen.t t/command-display-rc.t t/command-env.t t/command-exec.t t/command-help.t t/command-info.t t/command-install-cpanm.t t/command-install-from-archive.t t/command-install-patchperl.t t/command-install.t t/command-lib.t t/command-list.t t/current_perl.t t/current_shell.t t/do_system.t t/failure-command-install-cpanm.t t/failure-command-install-patchperl.t t/fake-bin/curl t/home.t t/http-program-control.t t/http-ua-detect-non-curl.t t/http-ua-detect.t t/http.t t/installation-perlbrew.t t/installation.t t/installation2.t t/installation3.t t/test.tar.gz t/test_helpers.pl t/unit-files-are-the-same.t .perlcriticrc000644000765000024 14113614277060 16132 0ustar00gugodstaff000000000000App-perlbrew-0.88color = 0 verbose = %f:%l:%c:[%p] %m => %r\n only = 1 include = RequireUseStrict ProhibitUnused Util.pm000644000765000024 153713614277060 20021 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/App/Perlbrewpackage App::Perlbrew::Util; use strict; use warnings; use 5.008; use Exporter 'import'; our @EXPORT = qw(uniq min editdist); sub uniq { my %seen; grep { !$seen{$_}++ } @_; } sub min(@) { my $m = $_[0]; for(@_) { $m = $_ if $_ < $m; } return $m; } # straight copy of Wikipedia's "Levenshtein Distance" sub editdist { my @a = split //, shift; my @b = split //, shift; # There is an extra row and column in the matrix. This is the # distance from the empty string to a substring of the target. my @d; $d[$_][0] = $_ for (0 .. @a); $d[0][$_] = $_ for (0 .. @b); for my $i (1 .. @a) { for my $j (1 .. @b) { $d[$i][$j] = ($a[$i-1] eq $b[$j-1] ? $d[$i-1][$j-1] : 1 + min($d[$i-1][$j], $d[$i][$j-1], $d[$i-1][$j-1])); } } return $d[@a][@b]; } 1; cpanfile000644000765000024 176213614277060 15202 0ustar00gugodstaff000000000000App-perlbrew-0.88requires 'CPAN::Perl::Releases' => '5.20191220'; requires 'Capture::Tiny' => '0.36'; requires 'Devel::PatchPerl' => '1.80'; requires 'Pod::Parser' => '1.63'; requires 'Pod::Usage' => '1.68'; requires 'File::Temp' => '0.2304'; requires 'JSON::PP' => '0'; requires 'local::lib' => '2.000014'; requires 'ExtUtils::MakeMaker' => '7.22'; on test => sub { requires 'File::Temp' => '0.2304'; requires 'File::Which' => '1.21'; requires 'IO::All' => '0.51'; requires 'Path::Class' => '0.33'; requires 'Test::Exception' => '0.32'; requires 'Test::More' => '1.001002'; requires 'Test::NoWarnings' => '1.04'; requires 'Test::Output' => '1.03'; requires 'Test::Simple' => '1.001002'; requires 'Test::Spec' => '0.47'; requires 'Test::TempDir::Tiny' => '0.016'; }; on develop => sub { requires 'Pod::Markdown' => '2.002'; }; http.t000644000765000024 342113614277060 15077 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use Test::Spec; use App::perlbrew; use File::Temp 'tempdir'; use IO::All; unless ($ENV{PERLBREW_DEV_TEST}) { plan skip_all => < sub { my ($output); before all => sub { App::perlbrew::http_get( "https://get.perlbrew.pl", undef, sub { $output = $_[0]; } ); }; it "calls the callback to assign content to \$output", sub { ok defined($output) && length($output) > 0; }; it "seems to download the correct content", sub { ok $output =~ m<\A #!/usr/bin/perl\n >x; ok $output =~ m< \$fatpacked\{"App/perlbrew.pm"\} >x; }; }; describe "App::perlbrew::http_download function, downloading the perlbrew-installer." => sub { my ($dir, $output, $download_error); before all => sub { $dir = tempdir( CLEANUP => 1 ); $output = "$dir/perlbrew-installer"; if (-f $output) { plan skip_all => < sub { ok(-f $output); }; it "seems to be downloading the right content" => sub { is(scalar(io($output)->getline), "#!/bin/sh\n"); }; }; runtests unless caller; 11.editdist.t000644000765000024 53113614277060 16130 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::More; use App::Perlbrew::Util qw< editdist >; is editdist(qw/Joe Jim/), 2; is editdist(qw/Jack Jill/), 3; is editdist(qw/Jim Jimmy/), 2; is editdist(qw/superman supergirl/), 4; is editdist(qw/supercalifragilisticexpyalligocious superman/), 29; is editdist(qw/foo bar/), 3; done_testing; perlbrew.pm000644000765000024 31600013614277060 17176 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/Apppackage App::perlbrew; use strict; use warnings; use 5.008; our $VERSION = "0.88"; use Config; BEGIN { # Special treat for Cwd to prevent it to be loaded from somewhere binary-incompatible with system perl. my @oldinc = @INC; @INC = ( $Config{sitelibexp}."/".$Config{archname}, $Config{sitelibexp}, @Config{qw}, ); require Cwd; @INC = @oldinc; } use Getopt::Long (); use CPAN::Perl::Releases; use JSON::PP 'decode_json'; use App::Perlbrew::Util; use App::Perlbrew::Path; use App::Perlbrew::Path::Root; ### global variables # set $ENV{SHELL} to executable path of parent process (= shell) if it's missing # (e.g. if this script was executed by a daemon started with "service xxx start") # ref: https://github.com/gugod/App-perlbrew/pull/404 $ENV{SHELL} ||= App::Perlbrew::Path->new ("/proc", getppid, "exe")->readlink if -d "/proc"; local $SIG{__DIE__} = sub { my $message = shift; warn $message; exit(1); }; our $CONFIG; our $PERLBREW_ROOT; our $PERLBREW_HOME; my @flavors = ( { d_option => 'usethreads', implies => 'multi', common => 1, opt => 'thread|threads' }, # threads is for backward compatibility { d_option => 'usemultiplicity', opt => 'multi' }, { d_option => 'uselongdouble', common => 1, opt => 'ld' }, { d_option => 'use64bitint', common => 1, opt => '64int' }, { d_option => 'use64bitall', implies => '64int', opt => '64all' }, { d_option => 'DEBUGGING', opt => 'debug' }, { d_option => 'cc=clang', opt => 'clang' }, ); my %flavor; my $flavor_ix = 0; for (@flavors) { my ($name) = $_->{opt} =~ /([^|]+)/; $_->{name} = $name; $_->{ix} = ++$flavor_ix; $flavor{$name} = $_; } for (@flavors) { if (my $implies = $_->{implies}) { $flavor{$implies}{implied_by} = $_->{name}; } } ### functions sub files_are_the_same { ## Check dev and inode num. Not useful on Win32. ## The for loop should always return false on Win32, as a result. my @files = @_; my @stats = map {[ stat($_) ]} @files; my $stats0 = join " ", @{$stats[0]}[0,1]; for (@stats) { return 0 if ((! defined($_->[1])) || $_->[1] == 0); unless ($stats0 eq join(" ", $_->[0], $_->[1])) { return 0; } } return 1 } { my %commands = ( curl => { test => '--version >/dev/null 2>&1', get => '--silent --location --fail -o - {url}', download => '--silent --location --fail -o {output} {url}', order => 1, # Exit code is 22 on 404s etc die_on_error => sub { die 'Page not retrieved; HTTP error code 400 or above.' if ($_[ 0 ] >> 8 == 22); }, }, wget => { test => '--version >/dev/null 2>&1', get => '--quiet -O - {url}', download => '--quiet -O {output} {url}', order => 2, # Exit code is not 0 on error die_on_error => sub { die 'Page not retrieved: fetch failed.' if ($_[ 0 ]); }, }, fetch => { test => '--version >/dev/null 2>&1', get => '-o - {url}', download => '-o {output} {url}', order => 3, # Exit code is 8 on 404s etc die_on_error => sub { die 'Server issued an error response.' if ($_[ 0 ] >> 8 == 8); }, } ); our $HTTP_USER_AGENT_PROGRAM; sub http_user_agent_program { $HTTP_USER_AGENT_PROGRAM ||= do { my $program; for my $p (sort {$commands{$a}{order}<=>$commands{$b}{order}} keys %commands) { my $code = system("$p $commands{$p}->{test}") >> 8; if ($code != 127) { $program = $p; last; } } unless ($program) { die "[ERROR] Cannot find a proper http user agent program. Please install curl or wget.\n"; } $program; }; die "[ERROR] Unrecognized http user agent program: $HTTP_USER_AGENT_PROGRAM. It can only be one of: ".join(",", keys %commands)."\n" unless $commands{$HTTP_USER_AGENT_PROGRAM}; return $HTTP_USER_AGENT_PROGRAM; } sub http_user_agent_command { my ($purpose, $params) = @_; my $ua = http_user_agent_program; my $cmd = $ua . " " . $commands{ $ua }->{ $purpose }; for (keys %$params) { $cmd =~ s!{$_}!$params->{$_}!g; } return ($ua, $cmd) if wantarray; return $cmd; } sub http_download { my ($url, $path) = @_; if (-e $path) { die "ERROR: The download target < $path > already exists.\n"; } my $partial = 0; local $SIG{TERM} = local $SIG{INT} = sub { $partial++ }; my $download_command = http_user_agent_command(download => { url => $url, output => $path }); my $status = system($download_command); if ($partial) { $path->unlink; return "ERROR: Interrupted."; } unless ($status == 0) { $path->unlink; return "ERROR: Failed to execute the command\n\n\t$download_command\n\nReason:\n\n\t$?"; } return 0; } sub http_get { my ($url, $header, $cb) = @_; if (ref($header) eq 'CODE') { $cb = $header; $header = undef; } my ($program, $command) = http_user_agent_command(get => { url => $url }); open my $fh, '-|', $command or die "open() pipe for '$command': $!"; local $/; my $body = <$fh>; close $fh; # check if the download has failed and die automatically $commands{ $program }{ die_on_error }->($?); return $cb ? $cb->($body) : $body; } } sub perl_version_to_integer { my $version = shift; my @v = split(/[\.\-_]/, $version); return undef if @v < 2; if ($v[1] <= 5) { $v[2] ||= 0; $v[3] = 0; } else { $v[3] ||= $v[1] >= 6 ? 9 : 0; $v[3] =~ s/[^0-9]//g; } return $v[1]*1000000 + $v[2]*1000 + $v[3]; } ### methods sub new { my($class, @argv) = @_; my %opt = ( original_argv => \@argv, args => [], yes => 0, force => 0, quiet => 0, D => [], U => [], A => [], sitecustomize => '', destdir => '', noman => '', variation => '', both => [], append => '', reverse => 0, verbose => 0, ); $opt{$_} = '' for keys %flavor; if (@argv) { # build a local @ARGV to allow us to use an older # Getopt::Long API in case we are building on an older system local (@ARGV) = @argv; Getopt::Long::Configure( 'pass_through', 'no_ignore_case', 'bundling', 'permute', # default behaviour except 'exec' ); $class->parse_cmdline(\%opt); $opt{args} = \@ARGV; # fix up the effect of 'bundling' foreach my $flags (@opt{qw(D U A)}) { foreach my $value (@{$flags}) { $value =~ s/^=//; } } } my $self = bless \%opt, $class; # Treat --root option same way as env variable PERLBREW_ROOT (with higher priority) $ENV{PERLBREW_ROOT} = $self->root ($opt{root}) if $opt{root}; $self->{builddir} = App::Perlbrew::Path->new ($self->{builddir}) if $opt{builddir}; # Ensure propagation of $PERLBREW_HOME and $PERLBREW_ROOT $self->root; $self->home; return $self; } sub parse_cmdline { my ($self, $params, @ext) = @_; my @f = map { $flavor{$_}{opt} || $_ } keys %flavor; return Getopt::Long::GetOptions( $params, 'yes', 'force|f', 'reverse', 'notest|n', 'quiet|q', 'verbose|v', 'as=s', 'append=s', 'help|h', 'version', 'root=s', 'switch', 'all', 'shell=s', 'no-patchperl', "builddir=s", # options passed directly to Configure 'D=s@', 'U=s@', 'A=s@', 'j=i', # options that affect Configure and customize post-build 'sitecustomize=s', 'destdir=s', 'noman', # flavors support 'both|b=s@', 'all-variations', 'common-variations', @f, @ext ) } sub root { my ($self, $new_root) = @_; $new_root ||= $PERLBREW_ROOT || $ENV{PERLBREW_ROOT} || App::Perlbrew::Path->new ($ENV{HOME}, "perl5", "perlbrew")->stringify unless $self->{root}; $self->{root} = $PERLBREW_ROOT = $new_root if defined $new_root; $self->{root} = App::Perlbrew::Path::Root->new ($self->{root}) unless ref $self->{root}; $self->{root} = App::Perlbrew::Path::Root->new ($self->{root}->stringify) unless $self->{root}->isa ('App::Perlbrew::Path::Root'); return $self->{root}; } sub home { my ($self, $new_home) = @_; $new_home ||= $PERLBREW_HOME || $ENV{PERLBREW_HOME} || App::Perlbrew::Path->new ($ENV{HOME}, ".perlbrew")->stringify unless $self->{home}; $self->{home} = $PERLBREW_HOME = $new_home if defined $new_home; $self->{home} = App::Perlbrew::Path->new ($self->{home}) unless ref $self->{home}; return $self->{home}; } sub builddir { my ($self) = @_; return $self->{builddir} || $self->root->build; } sub current_perl { my ($self, $v) = @_; $self->{current_perl} = $v if $v; return $self->{current_perl} || $self->env('PERLBREW_PERL') || ''; } sub current_lib { my ($self, $v) = @_; $self->{current_lib} = $v if $v; return $self->{current_lib} || $self->env('PERLBREW_LIB') || ''; } sub current_shell_is_bashish { my ($self) = @_; if (($self->current_shell eq 'bash') or ($self->current_shell eq 'zsh')) { return 1; } else { return 0; } } sub current_shell { my ($self, $x) = @_; $self->{current_shell} = $x if $x; return $self->{current_shell} ||= do { my $shell_name = App::Perlbrew::Path->new ($self->{shell} || $self->env('SHELL'))->basename; $shell_name =~ s/\d+$//; $shell_name; }; } sub current_env { my ($self) = @_; my $l = $self->current_lib; $l = "@" . $l if $l; return $self->current_perl . $l; } sub installed_perl_executable { my ($self, $name) = @_; die unless $name; my $executable = $self->root->perls ($name)->perl; return $executable if -e $executable; return ""; } sub configure_args { my ($self, $name) = @_; my $perl_cmd = $self->installed_perl_executable($name); my $code = 'while(($_,$v)=each(%Config)){print"$_ $v" if /config_arg/}'; my @output = split "\n" => $self->do_capture($perl_cmd, '-MConfig', '-wle', $code); my %arg; for(@output) { my ($k, $v) = split " ", $_, 2; $arg{$k} = $v; } if (wantarray) { return map { $arg{"config_arg$_"} } (1 .. $arg{config_argc}) } return $arg{config_args} } sub cpan_mirror { my ($self) = @_; unless($self->{cpan_mirror}) { $self->{cpan_mirror} = $self->env("PERLBREW_CPAN_MIRROR") || "http://www.cpan.org"; $self->{cpan_mirror} =~ s{/+$}{}; } return $self->{cpan_mirror}; } sub env { my ($self, $name) = @_; return $ENV{$name} if $name; return \%ENV; } sub is_shell_csh { my ($self) = @_; return 1 if $self->env('SHELL') =~ /(t?csh)/; return 0; } # Entry point method: handles all the arguments # and dispatches to an appropriate internal # method to execute the corresponding command. sub run { my($self) = @_; $self->run_command($self->args); } sub args { my ($self) = @_; # keep 'force' and 'yes' coherent across commands $self->{force} = $self->{yes} = 1 if ($self->{force} || $self->{yes}); return @{ $self->{args} }; } sub commands { my ($self) = @_; my $package = ref $self ? ref $self : $self; my @commands; my $symtable = do { no strict 'refs'; \%{$package . '::'}; }; foreach my $sym (keys %$symtable) { if ($sym =~ /^run_command_/) { my $glob = $symtable->{$sym}; if (ref($glob) eq 'CODE' || defined *$glob{CODE}) { # with perl >= 5.27 stash entry can points to a CV directly $sym =~ s/^run_command_//; $sym =~ s/_/-/g; push @commands, $sym; } } } return @commands; } sub find_similar_commands { my ($self, $command) = @_; my $SIMILAR_DISTANCE = 6; $command =~ s/_/-/g; my @commands = sort { $a->[1] <=> $b->[1] } map { my $d = editdist($_, $command); (($d < $SIMILAR_DISTANCE) ? [ $_, $d ] : ()) } $self->commands; if (@commands) { my $best = $commands[0][1]; @commands = map { $_->[0] } grep { $_->[1] == $best } @commands; } return @commands; } # This method is called in the 'run' loop # and executes every specific action depending # on the type of command. # # The first argument to this method is a self reference, # while the first "real" argument is the command to execute. # Other parameters after the command to execute are # considered as arguments for the command itself. # # In general the command is executed via a method named after the # command itself and with the 'run_command' prefix. For instance # the command 'exec' is handled by a method # `run_command_exec` # # If no candidates can be found, an execption is thrown # and a similar command is shown to the user. sub run_command { my ($self, $x, @args) = @_; my $command = $x; if ($self->{version}) { $x = 'version'; } elsif (!$x) { $x = 'help'; @args = (0, $self->{help} ? 2 : 0); } elsif ($x eq 'help') { @args = (0, 2) unless @args; } my $s = $self->can("run_command_$x"); unless ($s) { $x =~ y/-/_/; $s = $self->can("run_command_$x"); } unless ($s) { my @commands = $self->find_similar_commands($x); if (@commands > 1) { @commands = map { ' ' . $_ } @commands; die "Unknown command: `$command`. Did you mean one of the following?\n" . join("\n", @commands) . "\n"; } elsif (@commands == 1) { die "Unknown command: `$command`. Did you mean `$commands[0]`?\n"; } else { die "Unknown command: `$command`. Typo?\n"; } } $self->$s(@args); } sub run_command_version { my ($self) = @_; my $package = ref $self; my $version = $self->VERSION; print "$0 - $package/$version\n"; } # Provides help information about a command. # The idea is similar to the 'run_command' and 'run_command_$x' chain: # this method dispatches to a 'run_command_help_$x' method # if found in the class, otherwise it tries to extract the help # documentation via the POD of the class itself using the # section 'COMMAND: $x' with uppercase $x. sub run_command_help { my ($self, $status, $verbose, $return_text) = @_; require Pod::Usage; if ($status && !defined($verbose)) { if ($self->can("run_command_help_${status}")) { $self->can("run_command_help_${status}")->($self); } else { my $out = ""; open my $fh, ">", \$out; Pod::Usage::pod2usage( -exitval => "NOEXIT", -verbose => 99, -sections => "COMMAND: " . uc($status), -output => $fh, -noperldoc => 1 ); $out =~ s/\A[^\n]+\n//s; $out =~ s/^ //gm; if ($out =~ /\A\s*\Z/) { $out = "Cannot find documentation for '$status'\n\n"; } return "\n$out" if ($return_text); print "\n$out"; close $fh; } } else { Pod::Usage::pod2usage( -noperldoc => 1, -verbose => $verbose||0, -exitval => (defined $status ? $status : 1) ); } } # introspection for compgen my %comp_installed = ( use => 1, switch => 1, ); sub run_command_compgen { my($self, $cur, @args) = @_; $cur = 0 unless defined($cur); # do `tail -f bashcomp.log` for debugging if ($self->env('PERLBREW_DEBUG_COMPLETION')) { open my $log, '>>', 'bashcomp.log'; print $log "[$$] $cur of [@args]\n"; } my $subcommand = $args[1]; my $subcommand_completed = ($cur >= 2); if (!$subcommand_completed) { $self->_compgen($subcommand, $self->commands); } else { # complete args of a subcommand if ($comp_installed{$subcommand}) { if ($cur <= 2) { my $part; if (defined($part = $args[2])) { $part = qr/ \Q$part\E /xms; } $self->_compgen($part, map{ $_->{name} } $self->installed_perls()); } } elsif ($subcommand eq 'help') { if ($cur <= 2) { $self->_compgen($args[2], $self->commands()); } } else { # TODO } } } sub _firstrcfile { my ($self, @files) = @_; foreach my $path (@files) { return $path if -f App::Perlbrew::Path->new ($self->env('HOME'), $path); } return; } sub _compgen { my($self, $part, @reply) = @_; if (defined $part) { $part = qr/\A \Q$part\E /xms if ref($part) ne ref(qr//); @reply = grep { /$part/ } @reply; } foreach my $word(@reply) { print $word, "\n"; } } # Internal utility function. # Given a specific perl version, e.g., perl-5.27.4 # returns a string with a formatted version number such # as 05027004. Such string can be used as a number # in order to make either a string comparison # or a numeric comparison. # # In the case of cperl the major number is added by 6 # so that it would match the project claim of being # Perl 5+6 = 11. The final result is then # multiplied by a negative factor (-1) in order # to make cperl being "less" in the ordered list # than a normal Perl installation. # # The returned string is made by four pieces of two digits each: # MMmmppbb # where: # MM is the major Perl version (e.g., 5 -> 05) # mm is the minor Perl version (e.g. 27 -> 27) # pp is the patch level (e.g., 4 -> 04) # bb is the blead flag: it is 00 for a "normal" release, or 01 for a blead one sub comparable_perl_version { my ($self, $perl_version) = @_; my ($is_cperl, $is_blead) = (0, 0); my ($major, $minor, $patch) = (0, 0, 0); if ($perl_version =~ /^(?:(c?perl)-?)?(\d)\.(\d+).(\d+).*/) { $is_cperl = $1 && ($1 eq 'cperl'); $major = $2 + ($is_cperl ? 6 : 0); # major version $minor = $3; # minor version $patch = $4; # patch level } elsif ($perl_version =~ /^(?:(c?perl)-?)?-?(blead)$/) { # in the case of a blead release use a fake high number # to assume it is the "latest" release number available $is_cperl = $1 && ($1 eq 'cperl'); $is_blead = $2 && ($2 eq 'blead'); ($major, $minor, $patch) = (5, 99, 99); } return ($is_cperl ? -1 : 1) * sprintf('%02d%02d%02d%02d', $major + ($is_cperl ? 6 : 0), # major version $minor, # minor version $patch, # patch level $is_blead); # blead } # Internal method. # Performs a comparable sort of the perl versions specified as # list. sub sort_perl_versions { my ($self, @perls) = @_; return map { $_->[ 0 ] } sort { ( $self->{reverse} ? $a->[ 1 ] <=> $b->[ 1 ] : $b->[ 1 ] <=> $a->[ 1 ] ) } map { [ $_, $self->comparable_perl_version($_) ] } @perls; } sub run_command_available { my ($self) = @_; my $perls = $self->available_perls_with_urls(@_); my @installed = $self->installed_perls(@_); my $is_verbose = $self->{verbose}; # sort the keys of Perl installation (Randal to the rescue!) my @sorted_perls = $self->sort_perl_versions(keys %$perls); for my $available (@sorted_perls) { my $url = $perls->{$available}; my $ctime; for my $installed (@installed) { my $name = $installed->{name}; my $cur = $installed->{is_current}; if ($available eq $installed->{name}) { $ctime = $installed->{ctime}; last; } } printf "\n%1s %12s %s %s", $ctime ? 'i' : '', $available, ( $is_verbose ? $ctime ? "INSTALLED on $ctime via" : 'available from ' : ''), ( $is_verbose ? "<$url>" : '' ) ; } print "\n"; return @sorted_perls; } sub available_perls { my ($self) = @_; my $perls = $self->available_perls_with_urls; return $self->sort_perl_versions(keys %$perls); } sub available_perls_with_urls { my ($self, $dist, $opts) = @_; my $perls = {}; my @perllist; my $url = $self->{all} ? "https://www.cpan.org/src/5.0/" : "https://www.cpan.org/src/README.html" ; my $html = http_get($url, undef, undef); unless ($html) { die "\nERROR: Unable to retrieve the list of perls.\n\n"; } for (split "\n", $html) { my ($current_perl, $current_url); if ($self->{all}) { ($current_perl, $current_url) = ($2, $1) if m|\s*([^\s]+?)\s*|; } else { ($current_perl, $current_url ) = ($2, $1) if m|\s*([^\s]+?)\s*|; } # if we have a $current_perl add it to the available hash of perls if ($current_perl) { $current_perl =~ s/\.tar\.(bz2|gz)//; push @perllist, [ $current_perl, $current_url ]; $perls->{$current_perl} = $current_url; } } # we got impatient waiting for cpan.org to get updated to show 5.28... # So, we also fetch from metacpan for anything that looks perlish, # and we do our own processing to filter out the development # releases and minor versions when needed (using # filter_perl_available) $url = 'https://fastapi.metacpan.org/v1/release/versions/perl'; $html = http_get($url, undef, undef); unless ($html) { $html = ''; warn "\nERROR: Unable to retrieve list of perls from Metacpan.\n\n"; } while ($html =~ m{"(http(?:s?)://cpan\.metacpan\.org/[^"]+/(perl-5\.[0-9]+\.[0-9]+(?:-[A-Z0-9]+)?)\.tar\.(?:bz2|gz))"}g) { my ($current_perl, $current_url) = ($2, $1); push @perllist, [ $current_perl, $current_url ]; } foreach my $perl ($self->filter_perl_available(\@perllist)) { # We only want to add a Metacpan link if the www.cpan.org link # doesn't exist, and this assures that we do that properly. if (!exists($perls->{ $perl->[0] })) { $perls->{ $perl->[0] } = $perl->[1]; } } # cperl releases: https://github.com/perl11/cperl/tags my $cperl_remote = 'https://github.com'; my $url_cperl_release_list = $cperl_remote . '/perl11/cperl/tags'; $html = http_get($url_cperl_release_list); if ($html) { while ($html =~ m{href="(/perl11/cperl/archive/cperl-(5.+?)\.tar\.gz)"}xg) { $perls->{ "cperl-$2" } = $cperl_remote . $1; } } else { if ($self->{verbose}) { warn "\nWARN: Unable to retrieve the list of cperl releases.\n\n"; } } return $perls; } # $perllist is an arrayref of arrayrefs. The inner arrayrefs are of the # format: [ , ] # perl_name = something like perl-5.28.0 # perl_url = URL the Perl is available from. # # If $self->{all} is true, this just returns a list of the contents of # the list referenced by $perllist # # Otherwise, this looks for even middle numbers in the version and no # suffix (like -RC1) following the URL, and returns the list of # arrayrefs that so match # # If any "newest" Perl has a sub filter_perl_available { my ($self, $perllist) = @_; if ($self->{all}) { return @$perllist; } my %max_release; foreach my $perl (@$perllist) { my $ver = $perl->[0]; if ($ver !~ m/^perl-5\.[0-9]*[02468]\.[0-9]+$/) { next; } # most likely TRIAL or RC, or a DEV release my ($release_line, $minor) = $ver =~ m/^perl-5\.([0-9]+)\.([0-9]+)/; if (exists $max_release{$release_line}) { if ($max_release{$release_line}->[0] > $minor) { next; } # We have a newer release } $max_release{$release_line} = [ $minor, $perl ]; } return map { $_->[1] } values %max_release; } sub perl_release { my ($self, $version) = @_; my $mirror = $self->cpan_mirror(); # try CPAN::Perl::Releases my $tarballs = CPAN::Perl::Releases::perl_tarballs($version); my $x = (values %$tarballs)[0]; if ($x) { my $dist_tarball = (split("/", $x))[-1]; my $dist_tarball_url = "$mirror/authors/id/$x"; return ($dist_tarball, $dist_tarball_url); } # try src/5.0 symlinks, either perl-5.X or perl5.X; favor .tar.bz2 over .tar.gz my $index = http_get("http://www.cpan.org/src/5.0/"); if ($index) { for my $prefix ("perl-", "perl") { for my $suffix (".tar.bz2", ".tar.gz") { my $dist_tarball = "$prefix$version$suffix"; my $dist_tarball_url = "$mirror/src/5.0/$dist_tarball"; return ($dist_tarball, $dist_tarball_url) if ($index =~ /href\s*=\s*"\Q$dist_tarball\E"/ms); } } } my $json = http_get("'https://fastapi.metacpan.org/v1/release/_search?size=1&q=name:perl-${version}'"); my $result; unless ($json and $result = decode_json($json)->{hits}{hits}[0]) { die "ERROR: Failed to locate perl-${version} tarball."; } my ($dist_path, $dist_tarball) = $result->{_source}{download_url} =~ m[(/authors/id/.+/(perl-${version}.tar.(gz|bz2|xz)))$]; die "ERROR: Cannot find the tarball for perl-$version\n" if !$dist_path and !$dist_tarball; my $dist_tarball_url = "https://cpan.metacpan.org${dist_path}"; return ($dist_tarball, $dist_tarball_url); } sub cperl_release { my ($self, $version) = @_; my %url = ( "5.22.3" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.3/cperl-5.22.3.tar.gz", "5.22.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.2/cperl-5.22.2.tar.gz", "5.24.0-RC1" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.0-RC1/cperl-5.24.0-RC1.tar.gz", ); # my %digest => { # "5.22.3" => "bcf494a6b12643fa5e803f8e0d9cef26312b88fc", # "5.22.2" => "8615964b0a519cf70d69a155b497de98e6a500d0", # }; my $dist_tarball_url = $url{$version}or die "ERROR: Cannot find the tarball for cperl-$version\n"; my $dist_tarball = "cperl-${version}.tar.gz"; return ($dist_tarball, $dist_tarball_url); } sub release_detail_perl_local { my ($self, $dist, $rd) = @_; $rd ||= {}; my $error = 1; my $mirror = $self->cpan_mirror(); my $tarballs = CPAN::Perl::Releases::perl_tarballs($rd->{version}); if (keys %$tarballs) { for ("tar.bz2", "tar.gz") { if (my $x = $tarballs->{$_}) { $rd->{tarball_name} = (split("/", $x))[-1]; $rd->{tarball_url} = "$mirror/authors/id/$x"; $error = 0; last; } } } return ($error, $rd); } sub release_detail_perl_remote { my ($self, $dist, $rd) = @_; $rd ||= {}; my $error = 1; my $mirror = $self->cpan_mirror(); my $version = $rd->{version}; # try src/5.0 symlinks, either perl-5.X or perl5.X; favor .tar.bz2 over .tar.gz my $index = http_get("http://www.cpan.org/src/5.0/"); if ($index) { for my $prefix ("perl-", "perl") { for my $suffix (".tar.bz2", ".tar.gz") { my $dist_tarball = "$prefix$version$suffix"; my $dist_tarball_url = "$mirror/src/5.0/$dist_tarball"; if ($index =~ /href\s*=\s*"\Q$dist_tarball\E"/ms) { $rd->{tarball_url} = $dist_tarball_url; $rd->{tarball_name} = $dist_tarball; $error = 0; return ($error, $rd); } } } } my $json = http_get("'https://fastapi.metacpan.org/v1/release/_search?size=1&q=name:perl-${version}'"); my $result; unless ($json and $result = decode_json($json)->{hits}{hits}[0]) { die "ERROR: Failed to locate perl-${version} tarball."; } my ($dist_path, $dist_tarball) = $result->{_source}{download_url} =~ m[(/authors/id/.+/(perl-${version}.tar.(gz|bz2|xz)))$]; die "ERROR: Cannot find the tarball for perl-$version\n" if !$dist_path and !$dist_tarball; my $dist_tarball_url = "https://cpan.metacpan.org${dist_path}"; $rd->{tarball_name} = $dist_tarball; $rd->{tarball_url} = $dist_tarball_url; $error = 0; return ($error, $rd); } sub release_detail_cperl_local { my ($self, $dist, $rd) = @_; $rd ||= {}; my %url = ( "cperl-5.22.3" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.3/cperl-5.22.3.tar.gz", "cperl-5.22.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.22.2/cperl-5.22.2.tar.gz", "cperl-5.24.0-RC1" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.0-RC1/cperl-5.24.0-RC1.tar.gz", "cperl-5.24.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.2/cperl-5.24.2.tar.gz", "cperl-5.25.2" => "https://github.com/perl11/cperl/releases/download/cperl-5.24.2/cperl-5.25.2.tar.gz", "cperl-5.26.0" => "https://github.com/perl11/cperl/archive/cperl-5.26.0.tar.gz", "cperl-5.26.0-RC1" => "https://github.com/perl11/cperl/archive/cperl-5.26.0-RC1.tar.gz", "cperl-5.27.0" => "https://github.com/perl11/cperl/archive/cperl-5.27.0.tar.gz", ); my $error = 1; if (my $u = $url{$dist}) { $rd->{tarball_name} = "${dist}.tar.gz"; $rd->{tarball_url} = $u; $error = 0; } return ($error, $rd); } sub release_detail_cperl_remote { my ($self, $dist, $rd) = @_; $rd ||= {}; my $expect_href = "/perl11/cperl/archive/${dist}.tar.gz"; my $html = http_get('https://github.com/perl11/cperl/releases/tag/' . $dist); my $error = 1; if ($html =~ m{ {tarball_name} = "${dist}.tar.gz"; $rd->{tarball_url} = "https://github.com" . $1; $error = 0; } else { $error = 1; } return ($error, $rd); } sub release_detail { my ($self, $dist) = @_; my ($dist_type, $dist_version); ($dist_type, $dist_version) = $dist =~ /^ (?: (c?perl) -? )? ( [\d._]+ (?:-RC\d+)? |git|stable|blead)$/x; $dist_type = "perl" if $dist_version && !$dist_type; my $rd = { type => $dist_type, version => $dist_version, tarball_url => undef, tarball_name => undef, }; # dynamic methods: release_detail_perl_local, release_detail_cperl_local, release_detail_perl_remote, release_detail_cperl_remote my $m_local = "release_detail_${dist_type}_local"; my $m_remote = "release_detail_${dist_type}_remote"; my ($error) = $self->$m_local($dist, $rd); ($error) = $self->$m_remote($dist, $rd) if $error; if ($error) { die "ERROR: Fail to get the tarball URL for dist: $dist\n"; } return $rd; } sub run_command_init { my $self = shift; my @args = @_; if (@args && $args[0] eq '-') { if ($self->current_shell_is_bashish) { $self->run_command_init_in_bash; } exit 0; } $_->mkpath for (grep { ! -d $_ } map { $self->root->$_ } qw(perls dists build etc bin)); my ($f, $fh) = @_; my $etc_dir = $self->root->etc; for (["bashrc", "BASHRC_CONTENT"], ["cshrc", "CSHRC_CONTENT"], ["csh_reinit", "CSH_REINIT_CONTENT"], ["csh_wrapper", "CSH_WRAPPER_CONTENT"], ["csh_set_path", "CSH_SET_PATH_CONTENT"], ["perlbrew-completion.bash", "BASH_COMPLETION_CONTENT"], ["perlbrew.fish", "PERLBREW_FISH_CONTENT" ], ) { my ($file_name, $method) = @$_; my $path = $etc_dir->child ($file_name); if (! -f $path) { open($fh, ">", $path) or die "Fail to create $path. Please check the permission of $etc_dir and try `perlbrew init` again."; print $fh $self->$method; close $fh; } else { if (-w $path && open($fh, ">", $path)) { print $fh $self->$method; close $fh; } else { print "NOTICE: $path already exists and not updated.\n" unless $self->{quiet}; } } } my $root_dir = $self->root->stringify_with_tilde; # Skip this if we are running in a shell that already 'source's perlbrew. # This is true during a self-install/self-init. # Ref. https://github.com/gugod/App-perlbrew/issues/525 if ($ENV{PERLBREW_SHELLRC_VERSION}) { print("\nperlbrew root ($root_dir) is initialized.\n"); } else { my $shell = $self->current_shell; my ($code, $yourshrc); if ($shell =~ m/(t?csh)/) { $code = "source $root_dir/etc/cshrc"; $yourshrc = $1 . "rc"; } elsif ($shell =~ m/zsh\d?$/) { $code = "source $root_dir/etc/bashrc"; $yourshrc = $self->_firstrcfile(qw( .zshenv .bash_profile .bash_login .profile )) || ".zshenv"; } elsif ($shell =~ m/fish/) { $code = ". $root_dir/etc/perlbrew.fish"; $yourshrc = 'config/fish/config.fish'; } else { $code = "source $root_dir/etc/bashrc"; $yourshrc = $self->_firstrcfile(qw( .bash_profile .bash_login .profile )) || ".bash_profile"; } if ($self->home ne App::Perlbrew::Path->new ($self->env('HOME'), ".perlbrew")) { my $pb_home_dir = $self->home->stringify_with_tilde; if ( $shell =~ m/fish/ ) { $code = "set -x PERLBREW_HOME $pb_home_dir\n $code"; } else { $code = "export PERLBREW_HOME=$pb_home_dir\n $code"; } } print <root->bin ("perlbrew"); if (files_are_the_same($executable, $target)) { print "You are already running the installed perlbrew:\n\n $executable\n"; exit; } $self->root->bin->mkpath; open my $fh, "<", $executable; my @lines = <$fh>; close $fh; $lines[0] = $self->system_perl_shebang . "\n"; open $fh, ">", $target; print $fh $_ for @lines; close $fh; chmod(0755, $target); my $path = $target->stringify_with_tilde; print "perlbrew is installed: $path\n" unless $self->{quiet}; $self->run_command_init(); return; } sub do_install_git { my ($self, $dist) = @_; my $dist_name; my $dist_git_describe; my $dist_version; opendir my $cwd_orig, "."; chdir $dist; if (`git describe` =~ /v((5\.\d+\.\d+(?:-RC\d)?)(-\d+-\w+)?)$/) { $dist_name = 'perl'; $dist_git_describe = "v$1"; $dist_version = $2; } chdir $cwd_orig; require File::Spec; my $dist_extracted_dir = File::Spec->rel2abs($dist); $self->do_install_this(App::Perlbrew::Path->new ($dist_extracted_dir), $dist_version, "$dist_name-$dist_version"); return; } sub do_install_url { my ($self, $dist) = @_; my $dist_name = 'perl'; # need the period to account for the file extension my ($dist_version) = $dist =~ m/-([\d.]+(?:-RC\d+)?|git)\./; my ($dist_tarball) = $dist =~ m{/([^/]*)$}; if (! $dist_version && $dist =~ /blead\.tar.gz$/) { $dist_version = "blead"; } my $dist_tarball_path = $self->root->dists($dist_tarball); my $dist_tarball_url = $dist; $dist = "$dist_name-$dist_version"; # we install it as this name later if ($dist_tarball_url =~ m/^file/) { print "Installing $dist from local archive $dist_tarball_url\n"; $dist_tarball_url =~ s/^file:\/+/\//; $dist_tarball_path = $dist_tarball_url; } else { print "Fetching $dist as $dist_tarball_path\n"; my $error = http_download($dist_tarball_url, $dist_tarball_path); die "ERROR: Failed to download $dist_tarball_url\n$error\n" if $error; } my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path); $self->do_install_this($dist_extracted_path, $dist_version, $dist); return; } sub do_extract_tarball { my ($self, $dist_tarball) = @_; # Assuming the dir extracted from the tarball is named after the tarball. my $dist_tarball_basename = $dist_tarball->basename (qr/\.tar\.(?:gz|bz2|xz)$/); # Note that this is incorrect for blead. my $workdir = $self->builddir->child ($dist_tarball_basename); $workdir->rmpath; $workdir->mkpath; my $extracted_dir; # Was broken on Solaris, where GNU tar is probably # installed as 'gtar' - RT #61042 my $tarx = ($^O =~ /solaris|aix/ ? 'gtar ' : 'tar ') . ( $dist_tarball =~ m/xz$/ ? 'xJf' : $dist_tarball =~ m/bz2$/ ? 'xjf' : 'xzf' ); my $extract_command = "cd $workdir; $tarx $dist_tarball"; die "Failed to extract $dist_tarball" if system($extract_command); my @things = $workdir->children; if (@things == 1) { $extracted_dir = App::Perlbrew::Path->new ($things[0]); } unless (defined($extracted_dir) && -d $extracted_dir) { die "Failed to find the extracted directory under $workdir"; } return $extracted_dir; } sub do_install_blead { my ($self) = @_; # We always blindly overwrite anything that's already there, # because blead is a moving target. my $dist_tarball_path = $self->root->dists("blead.tar.gz"); unlink($dist_tarball_path) if -f $dist_tarball_path; $self->do_install_url("https://github.com/Perl/perl5/archive/blead.tar.gz"); } sub resolve_stable_version { my ($self) = @_; my ($latest_ver, $latest_minor); for my $cand ($self->available_perls) { my ($ver, $minor) = $cand =~ m/^perl-(5\.(6|8|[0-9]+[02468])\.[0-9]+)$/ or next; ($latest_ver, $latest_minor) = ($ver, $minor) if !defined $latest_minor || $latest_minor < $minor; } die "Can't determine latest stable Perl release\n" if !defined $latest_ver; return $latest_ver; } sub do_install_release { my ($self, $dist, $dist_version) = @_; my $rd = $self->release_detail($dist); my $dist_type = $rd->{type}; die "\"$dist\" does not look like a perl distribution name. " unless $dist_type && $dist_version =~ /^\d\./; my $dist_tarball = $rd->{tarball_name}; my $dist_tarball_url = $rd->{tarball_url}; my $dist_tarball_path = $self->root->dists ($dist_tarball); if (-f $dist_tarball_path) { print "Using the previously fetched ${dist_tarball}\n" if $self->{verbose}; } else { print "Fetching perl $dist_version as $dist_tarball_path\n" unless $self->{quiet}; $self->run_command_download($dist); } my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path); $self->do_install_this($dist_extracted_path, $dist_version, $dist); return; } sub run_command_install { my ($self, $dist, $opts) = @_; unless ($dist) { $self->run_command_help("install"); exit(-1); } $self->{dist_name} = $dist; # for help msg generation, set to non # normalized name my ($dist_type, $dist_version); if (($dist_type, $dist_version) = $dist =~ /^(?:(c?perl)-?)?([\d._]+(?:-RC\d+)?|git|stable|blead)$/) { $dist_version = $self->resolve_stable_version if $dist_version eq 'stable'; $dist_type ||= "perl"; $dist = "${dist_type}-${dist_version}"; # normalize dist name my $installation_name = ($self->{as} || $dist) . $self->{variation} . $self->{append}; if (not $self->{force} and $self->is_installed($installation_name)) { die "\nABORT: $installation_name is already installed.\n\n"; } if ($dist_type eq 'perl' && $dist_version eq 'blead') { $self->do_install_blead(); } else { $self->do_install_release($dist, $dist_version); } } # else it is some kind of special install: elsif (-d "$dist/.git") { $self->do_install_git($dist); } elsif (-f $dist) { $self->do_install_archive(App::Perlbrew::Path->new ($dist)); } elsif ($dist =~ m/^(?:https?|ftp|file)/) { # more protocols needed? $self->do_install_url($dist); } else { die "Unknown installation target \"$dist\", abort.\nPlease see `perlbrew help` " . "for the instruction on using the install command.\n\n"; } if ($self->{switch}) { if (defined(my $installation_name = $self->{installation_name})) { $self->switch_to($installation_name) } else { warn "can't switch, unable to infer final destination name.\n\n"; } } return; } sub check_and_calculate_variations { my $self = shift; my @both = @{$self->{both}}; if ($self->{'all-variations'}) { @both = keys %flavor; } elsif ($self->{'common-variations'}) { push @both, grep $flavor{$_}{common}, keys %flavor; } # check the validity of the varitions given via 'both' for my $both (@both) { $flavor{$both} or die "$both is not a supported flavor.\n\n"; $self->{$both} and die "options --both $both and --$both can not be used together"; if (my $implied_by = $flavor{$both}{implied_by}) { $self->{$implied_by} and die "options --both $both and --$implied_by can not be used together"; } } # flavors selected always my $start = ''; $start .= "-$_" for grep $self->{$_}, keys %flavor; # make variations my @var = $start; for my $both (@both) { my $append = join('-', $both, grep defined, $flavor{$both}{implies}); push @var, map "$_-$append", @var; } # normalize the variation names @var = map { join '-', '', sort { $flavor{$a}{ix} <=> $flavor{$b}{ix} } grep length, split /-+/, $_ } @var; s/(\b\w+\b)(?:-\1)+/$1/g for @var; # remove duplicate flavors # After inspecting perl Configure script this seems to be the most # reliable heuristic to determine if perl would have 64bit IVs by # default or not: if ($Config::Config{longsize} >= 8) { # We are in a 64bit platform. 64int and 64all are always set but # we don't want them to appear on the final perl name s/-64\w+//g for @var; } # remove duplicated variations my %var = map { $_ => 1 } @var; sort keys %var; } sub run_command_install_multiple { my ($self, @dists) = @_; unless (@dists) { $self->run_command_help("install-multiple"); exit(-1); } die "--switch can not be used with command install-multiple.\n\n" if $self->{switch}; die "--as can not be used when more than one distribution is given.\n\n" if $self->{as} and @dists > 1; my @variations = $self->check_and_calculate_variations; print join("\n", "Compiling the following distributions:", map(" $_$self->{append}", @dists), " with the following variations:", map((/-(.*)/ ? " $1" : " default"), @variations), "", ""); my @ok; for my $dist (@dists) { for my $variation (@variations) { local $@; eval { $self->{$_} = '' for keys %flavor; $self->{$_} = 1 for split /-/, $variation; $self->{variation} = $variation; $self->{installation_name} = undef; $self->run_command_install($dist); push @ok, $self->{installation_name}; }; if ($@) { $@ =~ s/\n+$/\n/; print "Installation of $dist$variation failed: $@"; } } } print join("\n", "", "The following perls have been installed:", map (" $_", grep defined, @ok), "", ""); return } sub run_command_download { my ($self, $dist) = @_; $dist = $self->resolve_stable_version if $dist && $dist eq 'stable'; my $rd = $self->release_detail($dist); my $dist_tarball = $rd->{tarball_name}; my $dist_tarball_url = $rd->{tarball_url}; my $dist_tarball_path = $self->root->dists ($dist_tarball); if (-f $dist_tarball_path && !$self->{force}) { print "$dist_tarball already exists\n"; } else { print "Download $dist_tarball_url to $dist_tarball_path\n" unless $self->{quiet}; my $error = http_download($dist_tarball_url, $dist_tarball_path); if ($error) { die "ERROR: Failed to download $dist_tarball_url\n$error\n"; } } } sub purify { my ($self, $envname) = @_; my @paths = grep { index($_, $self->home) < 0 && index($_, $self->root) < 0 } split /:/, $self->env($envname); return wantarray ? @paths : join(":", @paths); } sub system_perl_executable { my ($self) = @_; my $system_perl_executable = do { local $ENV{PATH} = $self->pristine_path; `perl -MConfig -e 'print \$Config{perlpath}'` }; return $system_perl_executable; } sub system_perl_shebang { my ($self) = @_; return $Config{sharpbang}. $self->system_perl_executable; } sub pristine_path { my ($self) = @_; return $self->purify("PATH"); } sub pristine_manpath { my ($self) = @_; return $self->purify("MANPATH"); } sub run_command_display_system_perl_executable { print $_[0]->system_perl_executable . "\n"; } sub run_command_display_system_perl_shebang { print $_[0]->system_perl_shebang . "\n"; } sub run_command_display_pristine_path { print $_[0]->pristine_path . "\n"; } sub run_command_display_pristine_manpath { print $_[0]->pristine_manpath . "\n"; } sub do_install_archive { require File::Basename; my $self = shift; my $dist_tarball_path = shift; my $dist_version; my $installation_name; if ($dist_tarball_path->basename =~ m{(c?perl)-?(5.+)\.tar\.(gz|bz2|xz)\Z}) { my $perl_variant = $1; $dist_version = $2; $installation_name = "${perl_variant}-${dist_version}"; } unless ($dist_version && $installation_name) { die "Unable to determine perl version from archive filename.\n\nThe archive name should look like perl-5.x.y.tar.gz or perl-5.x.y.tar.bz2 or perl-5.x.y.tar.xz\n"; } my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path); $self->do_install_this($dist_extracted_path, $dist_version, $installation_name); } sub do_install_this { my ($self, $dist_extracted_dir, $dist_version, $installation_name) = @_; my $variation = $self->{variation}; my $append = $self->{append}; my $looks_like_we_are_installing_cperl = $dist_extracted_dir =~ /\/ cperl- /x; $self->{dist_extracted_dir} = $dist_extracted_dir; $self->{log_file} = $self->root->child ("build.${installation_name}${variation}${append}.log"); my @d_options = @{ $self->{D} }; my @u_options = @{ $self->{U} }; my @a_options = @{ $self->{A} }; my $sitecustomize = $self->{sitecustomize}; my $destdir = $self->{destdir}; $installation_name = $self->{as} if $self->{as}; $installation_name .= "$variation$append"; $self->{installation_name} = $installation_name; if ($sitecustomize) { die "Could not read sitecustomize file '$sitecustomize'\n" unless -r $sitecustomize; push @d_options, "usesitecustomize"; } if ($self->{noman}) { push @d_options, qw/man1dir=none man3dir=none/; } for my $flavor (keys %flavor) { $self->{$flavor} and push @d_options, $flavor{$flavor}{d_option} } my $perlpath = $self->root->perls ($installation_name); my $patchperl = $self->root->bin ("patchperl"); unless (-x $patchperl && -f _) { $patchperl = "patchperl"; } unshift @d_options, qq(prefix=$perlpath); push @d_options, "usedevel" if $dist_version =~ /5\.\d[13579]|git|blead/; push @d_options, "usecperl" if $looks_like_we_are_installing_cperl; my $version = $self->comparable_perl_version($dist_version); if (defined $version and $version < $self->comparable_perl_version('5.6.0')) { # ancient perls do not support -A for Configure @a_options = (); } else { unless (grep { /eval:scriptdir=/} @a_options) { push @a_options, "'eval:scriptdir=${perlpath}/bin'"; } } print "Installing $dist_extracted_dir into " . $self->root->perls ($installation_name)->stringify_with_tilde . "\n\n"; print <{verbose}; This could take a while. You can run the following command on another shell to track the status: tail -f ${\ $self->{log_file}->stringify_with_tilde } INSTALL my @preconfigure_commands = ( "cd $dist_extracted_dir", "rm -f config.sh Policy.sh", ); push @preconfigure_commands, 'chmod -R +w .', $patchperl unless $self->{"no-patchperl"} || $looks_like_we_are_installing_cperl; my $configure_flags = $self->env("PERLBREW_CONFIGURE_FLAGS") || '-de'; my @configure_commands = ( "sh Configure $configure_flags " . join( ' ', ( map { qq{'-D$_'} } @d_options ), ( map { qq{'-U$_'} } @u_options ), ( map { qq{'-A$_'} } @a_options ), ), (defined $version and $version < $self->comparable_perl_version('5.8.9')) ? ("$^X -i -nle 'print unless /command-line/' makefile x2p/makefile") : () ); my $make = $ENV{MAKE} || ($^O eq "solaris" ? 'gmake' : 'make'); my @build_commands = ( $make . ' ' . ($self->{j} ? "-j$self->{j}" : "") ); # Test via "make test_harness" if available so we'll get # automatic parallel testing via $HARNESS_OPTIONS. The # "test_harness" target was added in 5.7.3, which was the last # development release before 5.8.0. my $test_target = "test"; if ($dist_version =~ /^5\.(\d+)\.(\d+)/ && ($1 >= 8 || $1 == 7 && $2 == 3)) { $test_target = "test_harness"; } local $ENV{TEST_JOBS}=$self->{j} if $test_target eq "test_harness" && ($self->{j}||1) > 1; my @install_commands = ("${make} install" . ($destdir ? " DESTDIR=$destdir" : q||)); unshift @install_commands, "${make} $test_target" unless $self->{notest}; # Whats happening here? we optionally join with && based on $self->{force}, but then subsequently join with && anyway? @install_commands = join " && ", @install_commands unless ($self->{force}); my $cmd = join " && ", ( @preconfigure_commands, @configure_commands, @build_commands, @install_commands ); $self->{log_file}->unlink; if ($self->{verbose}) { $cmd = "($cmd) 2>&1 | tee $self->{log_file}"; print "$cmd\n" if $self->{verbose}; } else { $cmd = "($cmd) >> '$self->{log_file}' 2>&1 "; } delete $ENV{$_} for qw(PERL5LIB PERL5OPT AWKPATH); if ($self->do_system($cmd)) { my $newperl = $self->root->perls ($installation_name)->perl; unless (-e $newperl) { $self->run_command_symlink_executables($installation_name); } eval { $self->append_log('##### Brew Finished #####') }; if ($sitecustomize) { my $capture = $self->do_capture("$newperl -V:sitelib"); my ($sitelib) = $capture =~ m/sitelib='([^']*)';/; $sitelib = $destdir . $sitelib if $destdir; $sitelib = App::Perlbrew::Path->new ($sitelib); $sitelib->mkpath; my $target = $sitelib->child ("sitecustomize.pl"); open my $dst, ">", $target or die "Could not open '$target' for writing: $!\n"; open my $src, "<", $sitecustomize or die "Could not open '$sitecustomize' for reading: $!\n"; print {$dst} do { local $/; <$src> }; } my $version_file = $self->root->perls ($installation_name)->version_file; if (-e $version_file) { $version_file->unlink or die "Could not unlink $version_file file: $!\n"; } print "$installation_name is successfully installed.\n"; } else { eval { $self->append_log('##### Brew Failed #####') }; die $self->INSTALLATION_FAILURE_MESSAGE; } return; } sub do_install_program_from_url { my ($self, $url, $program_name, $body_filter) = @_; my $out = $self->root->bin ($program_name); if (-f $out && !$self->{force} && !$self->{yes}) { require ExtUtils::MakeMaker; my $ans = ExtUtils::MakeMaker::prompt("\n$out already exists, are you sure to override ? [y/N]", "N"); if ($ans !~ /^Y/i) { print "\n$program_name installation skipped.\n\n" unless $self->{quiet}; return; } } my $body = http_get($url) or die "\nERROR: Failed to retrieve $program_name executable.\n\n"; unless ($body =~ m{\A#!/}s) { my $x = App::Perlbrew::Path->new ($self->env('TMPDIR') || "/tmp", "${program_name}.downloaded.$$"); my $message = "\nERROR: The downloaded $program_name program seem to be invalid. Please check if the following URL can be reached correctly\n\n\t$url\n\n...and try again latter."; unless (-f $x) { open my $OUT, ">", $x; print $OUT $body; close($OUT); $message .= "\n\nThe previously downloaded file is saved at $x for manual inspection.\n\n"; } die $message; } if ($body_filter && ref($body_filter) eq "CODE") { $body = $body_filter->($body); } $self->root->bin->mkpath; open my $OUT, '>', $out or die "cannot open file($out): $!"; print $OUT $body; close $OUT; chmod 0755, $out; print "\n$program_name is installed to\n\n $out\n\n" unless $self->{quiet}; } sub do_exit_with_error_code { my ($self, $code) = @_; exit($code); } sub do_system_with_exit_code { my ($self, @cmd) = @_; return system(@cmd); } sub do_system { my ($self, @cmd) = @_; return ! $self->do_system_with_exit_code(@cmd); } sub do_capture { my ($self, @cmd) = @_; require Capture::Tiny; return Capture::Tiny::capture(sub { $self->do_system(@cmd); }); } sub format_perl_version { my $self = shift; my $version = shift; return sprintf "%d.%d.%d", substr($version, 0, 1), substr($version, 2, 3), substr($version, 5) || 0; } sub installed_perls { my $self = shift; my @result; my $root = $self->root; for my $installation ($root->perls->list) { my $name = $installation->name; my $executable = $installation->perl; next unless -f $executable; my $version_file = $installation->version_file; my $ctime = localtime((stat $executable)[ 10 ]); # localtime in scalar context! my $orig_version; if (-e $version_file) { open my $fh, '<', $version_file; local $/; $orig_version = <$fh>; chomp $orig_version; } else { $orig_version = `$executable -e 'print \$]'`; if (defined $orig_version and length $orig_version) { if (open my $fh, '>', $version_file ) { print {$fh} $orig_version; } } } push @result, { name => $name, orig_version=> $orig_version, version => $self->format_perl_version($orig_version), is_current => ($self->current_perl eq $name) && !($self->current_lib), libs => [ $self->local_libs($name) ], executable => $executable, dir => $installation, comparable_version => $self->comparable_perl_version($orig_version), ctime => $ctime, }; } return sort { ( $self->{reverse} ? ( $a->{comparable_version} <=> $b->{comparable_version} or $b->{name} cmp $a->{name} ) : ( $b->{comparable_version} <=> $a->{comparable_version} or $a->{name} cmp $b->{name} ) ) } @result; } sub compose_locallib { my ($self, $perl_name, $lib_name) = @_; return join '@', $perl_name, $lib_name; } sub decompose_locallib { my ($self, $name) = @_; return split '@', $name; } sub enforce_localib { my ($self, $name) = @_; $name =~ s/^/@/ unless $name =~ m/@/; return $name; } sub local_libs { my ($self, $perl_name) = @_; my $current = $self->current_env; my @libs = map { my $name = $_->basename; my ($p, $l) = $self->decompose_locallib ($name); +{ name => $name, is_current => $name eq $current, perl_name => $p, lib_name => $l, dir => $_, } } $self->home->child ("libs")->children; if ($perl_name) { @libs = grep { $perl_name eq $_->{perl_name} } @libs; } return @libs; } sub is_installed { my ($self, $name) = @_; return grep { $name eq $_->{name} } $self->installed_perls; } sub assert_known_installation { my ($self, $name) = @_; return 1 if $self->is_installed($name); die "ERROR: The installation \"$name\" is unknown\n\n"; } # Return a hash of PERLBREW_* variables sub perlbrew_env { my ($self, $name) = @_; my ($perl_name, $lib_name); if ($name) { ($perl_name, $lib_name) = $self->resolve_installation_name($name); unless ($perl_name) { die "\nERROR: The installation \"$name\" is unknown.\n\n"; } unless (!$lib_name || grep { $_->{lib_name} eq $lib_name } $self->local_libs($perl_name)) { die "\nERROR: The lib name \"$lib_name\" is unknown.\n\n"; } } my %env = ( PERLBREW_VERSION => $VERSION, PERLBREW_PATH => $self->root->bin, PERLBREW_MANPATH => "", PERLBREW_ROOT => $self->root ); require local::lib; my $pb_home = $self->home; my $current_local_lib_root = $self->env("PERL_LOCAL_LIB_ROOT") || ""; my $current_local_lib_context = local::lib->new; my @perlbrew_local_lib_root = uniq(grep { /\Q${pb_home}\E/ } split(/:/, $current_local_lib_root)); if ($current_local_lib_root =~ /^\Q${pb_home}\E/) { $current_local_lib_context = $current_local_lib_context->activate($_) for @perlbrew_local_lib_root; } if ($perl_name) { my $installation = $self->root->perls ($perl_name); if(-d $installation->child("bin")) { $env{PERLBREW_PERL} = $perl_name; $env{PERLBREW_PATH} .= ":" . $installation->child ("bin"); $env{PERLBREW_MANPATH} = $installation->child ("man") } if ($lib_name) { $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root; my $base = $self->home->child ("libs", "${perl_name}\@${lib_name}"); if (-d $base) { $current_local_lib_context = $current_local_lib_context->activate($base); if ($self->env('PERLBREW_LIB_PREFIX')) { unshift @{$current_local_lib_context->libs}, $self->env('PERLBREW_LIB_PREFIX'); } $env{PERLBREW_PATH} = $base->child ("bin") . ":" . $env{PERLBREW_PATH}; $env{PERLBREW_MANPATH} = $base->child ("man") . ":" . $env{PERLBREW_MANPATH}; $env{PERLBREW_LIB} = $lib_name; } } else { $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root; $env{PERLBREW_LIB} = undef; } my %ll_env = $current_local_lib_context->build_environment_vars; delete $ll_env{PATH}; for my $key (keys %ll_env) { $env{$key} = $ll_env{$key}; } } else { $current_local_lib_context = $current_local_lib_context->deactivate($_) for @perlbrew_local_lib_root; my %ll_env = $current_local_lib_context->build_environment_vars; delete $ll_env{PATH}; for my $key (keys %ll_env) { $env{$key} = $ll_env{$key}; } $env{PERLBREW_LIB} = undef; $env{PERLBREW_PERL} = undef; } return %env; } sub run_command_list { my $self = shift; my $is_verbose = $self->{verbose}; for my $i ($self->installed_perls) { printf "%-2s%-20s %-20s %s\n", $i->{is_current} ? '*' : '', $i->{name}, ( $is_verbose ? (index($i->{name}, $i->{version}) < 0) ? "($i->{version})" : '' : '' ), ( $is_verbose ? "(installed on $i->{ctime})" : '' ); for my $lib (@{$i->{libs}}) { print $lib->{is_current} ? "* " : " ", $lib->{name}, "\n" } } return 0; } sub launch_sub_shell { my ($self, $name) = @_; my $shell = $self->env('SHELL'); my $shell_opt = ""; if ($shell =~ /\/zsh\d?$/) { $shell_opt = "-d -f"; if ($^O eq 'darwin') { my $root_dir = $self->root; print <<"WARNINGONMAC" -------------------------------------------------------------------------------- WARNING: zsh perlbrew sub-shell is not working on Mac OSX Lion. It is known that on MacOS Lion, zsh always resets the value of PATH on launching a sub-shell. Effectively nullify the changes required by perlbrew sub-shell. You may `echo \$PATH` to examine it and if you see perlbrew related paths are in the end, instead of in the beginning, you are unfortunate. You are advised to include the following line to your ~/.zshenv as a better way to work with perlbrew: source $root_dir/etc/bashrc -------------------------------------------------------------------------------- WARNINGONMAC } } my %env = ($self->perlbrew_env($name), PERLBREW_SKIP_INIT => 1); unless ($ENV{PERLBREW_VERSION}) { my $root = $self->root; # The user does not source bashrc/csh in their shell initialization. $env{PATH} = $env{PERLBREW_PATH} . ":" . join ":", grep { !/$root\/bin/ } split ":", $ENV{PATH}; $env{MANPATH} = $env{PERLBREW_MANPATH} . ":" . join ":", grep { !/$root\/man/ } ( defined($ENV{MANPATH}) ? split(":", $ENV{MANPATH}) : () ); } my $command = "env "; while (my ($k, $v) = each(%env)) { no warnings "uninitialized"; $command .= "$k=\"$v\" "; } $command .= " $shell $shell_opt"; my $pretty_name = defined($name) ? $name : "the default perl"; print "\nA sub-shell is launched with $pretty_name as the activated perl. Run 'exit' to finish it.\n\n"; exec($command); } sub run_command_use { my $self = shift; my $perl = shift; if ( !$perl ) { my $current = $self->current_env; if ($current) { print "Currently using $current\n"; } else { print "No version in use; defaulting to system\n"; } return; } $self->launch_sub_shell($perl); } sub run_command_switch { my ($self, $dist, $alias) = @_; unless ( $dist ) { my $current = $self->current_env; printf "Currently switched %s\n", ( $current ? "to $current" : 'off' ); return; } $self->switch_to($dist, $alias); } sub switch_to { my ($self, $dist, $alias) = @_; die "Cannot use for alias something that starts with 'perl-'\n" if $alias && $alias =~ /^perl-/; die "${dist} is not installed\n" unless -d $self->root->perls ($dist); if ($self->env("PERLBREW_SHELLRC_VERSION") && $self->current_shell_is_bashish) { local $ENV{PERLBREW_PERL} = $dist; my $HOME = $self->env('HOME'); my $pb_home = $self->home; $pb_home->mkpath; system("$0 env $dist > " . $pb_home->child ("init")); print "Switched to $dist.\n\n"; } else { $self->launch_sub_shell($dist); } } sub run_command_off { my $self = shift; $self->launch_sub_shell; } sub run_command_switch_off { my $self = shift; my $pb_home = $self->home; $pb_home->mkpath; system("env PERLBREW_PERL= $0 env > " . $pb_home->child ("init")); print "\nperlbrew is switched off. Please exit this shell and start a new one to make it effective.\n"; print "To immediately make it effective, run this line in this terminal:\n\n exec @{[ $self->env('SHELL') ]}\n\n"; } sub run_command_env { my($self, $name) = @_; my %env = $self->perlbrew_env($name); my @statements; for my $k (sort keys %env) { my $v = $env{$k}; if (defined($v) && $v ne '') { $v =~ s/(\\")/\\$1/g; push @statements, ["set", $k, $v]; } else { if (exists $ENV{$k}) { push @statements, ["unset", $k]; } } } if ($self->env('SHELL') =~ /(ba|k|z|\/)sh\d?$/) { for (@statements) { my ($o, $k, $v) = @$_; if ($o eq 'unset') { print "unset $k\n"; } else { $v =~ s/(\\")/\\$1/g; print "export $k=\"$v\"\n"; } } } else { for (@statements) { my ($o, $k, $v) = @$_; if ($o eq 'unset') { print "unsetenv $k\n"; } else { print "setenv $k \"$v\"\n"; } } } } sub run_command_symlink_executables { my($self, @perls) = @_; my $root = $self->root; unless (@perls) { @perls = map { $_->name } grep { -d $_ && ! -l $_ } $root->perls->list; } for my $perl (@perls) { for my $executable ($root->perls ($perl)->bin->children) { my ($name, $version) = $executable =~ m/bin\/(.+?)(5\.\d.*)?$/; next unless $version; $executable->symlink ($root->perls ($perl)->bin($name)); $executable->symlink ($root->perls ($perl)->perl) if $name eq "cperl"; } } } sub run_command_install_patchperl { my ($self) = @_; $self->do_install_program_from_url( 'https://raw.githubusercontent.com/gugod/patchperl-packing/master/patchperl', 'patchperl', sub { my ($body) = @_; $body =~ s/\A#!.+?\n/ $self->system_perl_shebang . "\n" /se; return $body; } ); } sub run_command_install_cpanm { my ($self) = @_; $self->do_install_program_from_url('https://raw.githubusercontent.com/miyagawa/cpanminus/master/cpanm' => 'cpanm'); } sub run_command_install_cpm { my ($self) = @_; $self->do_install_program_from_url('https://raw.githubusercontent.com/skaji/cpm/master/cpm' => 'cpm'); } sub run_command_self_upgrade { my ($self) = @_; my $TMPDIR = $ENV{TMPDIR} || "/tmp"; my $TMP_PERLBREW = App::Perlbrew::Path->new ($TMPDIR, "perlbrew"); require FindBin; unless (-w $FindBin::Bin) { die "Your perlbrew installation appears to be system-wide. Please upgrade through your package manager.\n"; } http_get('https://raw.githubusercontent.com/gugod/App-perlbrew/master/perlbrew', undef, sub { my ($body) = @_; open my $fh, '>', $TMP_PERLBREW or die "Unable to write perlbrew: $!"; print $fh $body; close $fh; }); chmod 0755, $TMP_PERLBREW; my $new_version = qx($TMP_PERLBREW version); chomp $new_version; if ($new_version =~ /App::perlbrew\/(\d+\.\d+)$/) { $new_version = $1; } else { die "Unable to detect version of new perlbrew!\n"; } if ($new_version <= $VERSION) { print "Your perlbrew is up-to-date.\n"; return; } system $TMP_PERLBREW, "self-install"; $TMP_PERLBREW->unlink; } sub run_command_uninstall { my ($self, $target) = @_; unless ($target) { $self->run_command_help("uninstall"); exit(-1); } my @installed = $self->installed_perls(@_); my ($to_delete) = grep { $_->{name} eq $target } @installed; die "'$target' is not installed\n" unless $to_delete; my @dir_to_delete; for (@{$to_delete->{libs}}) { push @dir_to_delete, $_->{dir}; } push @dir_to_delete, $to_delete->{dir}; my $ans = ($self->{yes}) ? "Y": undef; if (!defined($ans)) { require ExtUtils::MakeMaker; $ans = ExtUtils::MakeMaker::prompt("\nThe following perl+lib installation(s) will be deleted:\n\n\t" . join("\n\t", @dir_to_delete) . "\n\n... are you sure ? [y/N]", "N"); } if ($ans =~ /^Y/i) { for (@dir_to_delete) { print "Deleting: $_\n" unless $self->{quiet}; App::Perlbrew::Path->new ($_)->rmpath; print "Deleted: $_\n" unless $self->{quiet}; } } else { print "\nOK. Not deleting anything.\n\n"; return; } } sub run_command_exec { my $self = shift; my %opts; local (@ARGV) = @{$self->{original_argv}}; Getopt::Long::Configure ('require_order'); my @command_options = ('with=s', 'halt-on-error', 'min=s', 'max=s'); $self->parse_cmdline (\%opts, @command_options); shift @ARGV; # "exec" $self->parse_cmdline (\%opts, @command_options); my @exec_with; if ($opts{with}) { my %installed = map { $_->{name} => $_ } map { ($_, @{$_->{libs}}) } $self->installed_perls; my $d = ($opts{with} =~ m/ /) ? qr( +) : qr(,+); my @with = grep { $_ } map { my ($p, $l) = $self->resolve_installation_name($_); $p .= "\@$l" if $l; $p; } split $d, $opts{with}; @exec_with = map { $installed{$_} } @with; } else { @exec_with = map { ($_, @{$_->{libs}}) } $self->installed_perls; } if ($opts{min}) { # TODO use comparable version. # For now, it doesn't produce consistent results for 5.026001 and 5.26.1 @exec_with = grep { $_->{orig_version} >= $opts{min} } @exec_with; }; if ($opts{max}) { @exec_with = grep { $_->{orig_version} <= $opts{max} } @exec_with; }; if (0 == @exec_with) { print "No perl installation found.\n" unless $self->{quiet}; } my $no_header = 0; if (1 == @exec_with) { $no_header = 1; } my $overall_success = 1; for my $i ( @exec_with ) { next if -l $self->root->perls ($i->{name}); # Skip Aliases my %env = $self->perlbrew_env($i->{name}); next if !$env{PERLBREW_PERL}; local %ENV = %ENV; $ENV{$_} = defined $env{$_} ? $env{$_} : '' for keys %env; $ENV{PATH} = join(':', $env{PERLBREW_PATH}, $ENV{PATH}); $ENV{MANPATH} = join(':', $env{PERLBREW_MANPATH}, $ENV{MANPATH}||""); $ENV{PERL5LIB} = $env{PERL5LIB} || ""; print "$i->{name}\n==========\n" unless $no_header || $self->{quiet}; if (my $err = $self->do_system_with_exit_code(@ARGV)) { my $exit_code = $err >> 8; # return 255 for case when process was terminated with signal, in that case real exit code is useless and weird $exit_code = 255 if $exit_code > 255; $overall_success = 0; unless ($self->{quiet}) { print "Command terminated with non-zero status.\n"; print STDERR "Command [" . join(' ', map { /\s/ ? "'$_'" : $_ } @ARGV) . # trying reverse shell escapes - quote arguments containing spaces "] terminated with exit code $exit_code (\$? = $err) under the following perl environment:\n"; print STDERR $self->format_info_output; } $self->do_exit_with_error_code($exit_code) if ($opts{'halt-on-error'}); } print "\n" unless $self->{quiet} || $no_header; } $self->do_exit_with_error_code(1) unless $overall_success; } sub run_command_clean { my ($self) = @_; my $root = $self->root; my @build_dirs = $root->build->children; for my $dir (@build_dirs) { print "Removing $dir\n"; App::Perlbrew::Path->new ($dir)->rmpath; } my @tarballs = $root->dists->children; for my $file ( @tarballs ) { print "Removing $file\n"; $file->unlink; } print "\nDone\n"; } sub run_command_alias { my ($self, $cmd, $name, $alias) = @_; unless ($cmd) { $self->run_command_help("alias"); exit(-1); } my $path_name = $self->root->perls ($name) if $name; my $path_alias = $self->root->perls ($alias) if $alias; if ($alias && -e $path_alias && !-l $path_alias) { die "\nABORT: The installation name `$alias` is not an alias, cannot override.\n\n"; } if ($cmd eq 'create') { $self->assert_known_installation($name); if ($self->is_installed($alias) && !$self->{force}) { die "\nABORT: The installation `${alias}` already exists. Cannot override.\n\n"; } $path_alias->unlink; $path_name->symlink ($path_alias); } elsif ($cmd eq 'delete') { $self->assert_known_installation($name); unless (-l $path_name) { die "\nABORT: The installation name `$name` is not an alias, cannot remove.\n\n"; } $path_name->unlink; } elsif ($cmd eq 'rename') { $self->assert_known_installation($name); unless (-l $path_name) { die "\nABORT: The installation name `$name` is not an alias, cannot rename.\n\n"; } if (-l $path_alias && !$self->{force}) { die "\nABORT: The alias `$alias` already exists, cannot rename to it.\n\n"; } rename($path_name, $path_alias); } elsif ($cmd eq 'help') { $self->run_command_help("alias"); } else { die "\nERROR: Unrecognized action: `${cmd}`.\n\n"; } } sub run_command_display_bashrc { print BASHRC_CONTENT(); } sub run_command_display_cshrc { print CSHRC_CONTENT(); } sub run_command_display_installation_failure_message { my ($self) = @_; } sub run_command_lib { my ($self, $subcommand, @args) = @_; unless ($subcommand) { $self->run_command_help("lib"); exit(-1); } my $sub = "run_command_lib_$subcommand"; if ($self->can($sub)) { $self->$sub(@args); } else { print "Unknown command: $subcommand\n"; } } sub run_command_lib_create { my ($self, $name) = @_; die "ERROR: No lib name\n", $self->run_command_help("lib", undef, 'return_text') unless $name; $name = $self->enforce_localib ($name); my ($perl_name, $lib_name) = $self->resolve_installation_name($name); if (!$perl_name) { my ($perl_name, $lib_name) = $self->decompose_locallib ($name); die "ERROR: '$perl_name' is not installed yet, '$name' cannot be created.\n"; } my $fullname = $self->compose_locallib ($perl_name, $lib_name); my $dir = $self->home->child ("libs", $fullname); if (-d $dir) { die "$fullname is already there.\n"; } $dir->mkpath; print "lib '$fullname' is created.\n" unless $self->{quiet}; return; } sub run_command_lib_delete { my ($self, $name) = @_; die "ERROR: No lib to delete\n", $self->run_command_help("lib", undef, 'return_text') unless $name; $name = $self->enforce_localib ($name); my ($perl_name, $lib_name) = $self->resolve_installation_name($name); my $fullname = $self->compose_locallib ($perl_name, $lib_name); my $current = $self->current_env; my $dir = $self->home->child ("libs", $fullname); if (-d $dir) { if ($fullname eq $current) { die "$fullname is currently being used in the current shell, it cannot be deleted.\n"; } $dir->rmpath; print "lib '$fullname' is deleted.\n" unless $self->{quiet}; } else { die "ERROR: '$fullname' does not exist.\n"; } return; } sub run_command_lib_list { my ($self) = @_; my $dir = $self->home->child ("libs"); return unless -d $dir; opendir my $dh, $dir or die "open $dir failed: $!"; my @libs = grep { !/^\./ && /\@/ } readdir($dh); my $current = $self->current_env; for (@libs) { print $current eq $_ ? "* " : " "; print "$_\n"; } } sub run_command_upgrade_perl { my ($self) = @_; my $PERL_VERSION_RE = qr/(\d+)\.(\d+)\.(\d+)/; my ($current) = grep { $_->{is_current} } $self->installed_perls; unless (defined $current) { print "no perlbrew environment is currently in use\n"; exit(1); } my ($major, $minor, $release); if ($current->{version} =~ /^$PERL_VERSION_RE$/) { ($major, $minor, $release) = ($1, $2, $3); } else { print "unable to parse version '$current->{version}'\n"; exit(1); } my @available = grep { /^perl-$major\.$minor/ } $self->available_perls; my $latest_available_perl = $release; foreach my $perl (@available) { if ($perl =~ /^perl-$PERL_VERSION_RE$/) { my $this_release = $3; if ($this_release > $latest_available_perl) { $latest_available_perl = $this_release; } } } if ($latest_available_perl == $release) { print "This perlbrew environment ($current->{name}) is already up-to-date.\n"; exit(0); } my $dist_version = "$major.$minor.$latest_available_perl"; my $dist = "perl-$dist_version"; print "Upgrading $current->{name} to $dist_version\n" unless $self->{quiet}; local $self->{as} = $current->{name}; local $self->{dist_name} = $dist; require Config ; my @d_options = map { '-D' . $flavor{$_}->{d_option}} keys %flavor ; my %sub_config = map { $_ => $Config{$_}} grep { /^config_arg\d/} keys %Config ; for my $value (values %sub_config) { my $value_wo_D = $value; $value_wo_D =~ s/^-D//; push @{$self->{D}} , $value_wo_D if grep {/$value/} @d_options; } $self->do_install_release($dist, $dist_version); } # Executes the list-modules command. # This routine launches a new perl instance that, thru # ExtUtils::Installed prints out all the modules # in the system. If an argument is passed to the # subroutine it is managed as a filename # to which prints the list of modules. sub run_command_list_modules { my ($self, $output_filename) = @_; my $class = ref($self) || __PACKAGE__; # avoid something that does not seem as a filename to print # output to... undef $output_filename if (! scalar($output_filename)); my $name = $self->current_env; if (-l (my $path = $self->root->perls ($name))) { $name = $path->readlink->basename; } my $app = $class->new( qw(--quiet exec --with), $name, 'perl', '-MExtUtils::Installed', '-le', sprintf('BEGIN{@INC=grep {$_ ne q!.!} @INC}; %s print {%s} $_ for grep {$_ ne q!Perl!} ExtUtils::Installed->new->modules;', $output_filename ? sprintf('open my $output_fh, \'>\', "%s"; ', $output_filename) : '', $output_filename ? '$output_fh' : 'STDOUT') ); $app->run; } sub resolve_installation_name { my ($self, $name) = @_; die "App::perlbrew->resolve_installation_name requires one argument." unless $name; my ($perl_name, $lib_name) = $self->decompose_locallib ($name); $perl_name = $name unless $lib_name; $perl_name ||= $self->current_perl; if (!$self->is_installed($perl_name)) { if ($self->is_installed("perl-${perl_name}") ) { $perl_name = "perl-${perl_name}"; } else { return undef; } } return wantarray ? ($perl_name, $lib_name) : $perl_name; } # Implementation of the 'clone-modules' command. # # This method accepts a destination and source installation # of Perl to clone modules from and into. # For instance calling # $app->run_command_clone_modules($perl_a, $perl_b); # installs all modules that have been installed on Perl A # to the instance of Perl B. # The source instance is optional, that is if the method # is invoked with a single argument, the currently # running instance is used as source. Therefore the # two following calls are the same: # # $app->run_command_clone_modules( $self->current_perl, $perl_b ); # $app->run_command_clone_modules( $perl_b ); # # Of course, both Perl installation must exist on this # perlbrew enviroment. # # The method extracts the modules installed on the source Perl # instance and put them on a temporary file, such file is then # passed to another instance of the application to # execute cpanm on it. The final result is the installation # of source modules into the destination instance. sub run_command_clone_modules { my $self = shift; # default to use the currently installation my ( $dst_perl, $src_perl ); # the first argument is the destination, the second # optional argument is the source version, default # to use the current installation $dst_perl = pop || $self->current_env; $src_perl = pop || $self->current_env; # check source and destination do exist undef $src_perl if (! $self->resolve_installation_name($src_perl)); undef $dst_perl if (! $self->resolve_installation_name($dst_perl)); if ( ! $src_perl || ! $dst_perl || $src_perl eq $dst_perl ){ # cannot understand from where to where or # the user did specify the same versions $self->run_command_help('clone-modules'); exit(-1); } # I need to run an application to do the module listing. # and get the result back so to handle it and pass # to the exec subroutine. The solution I found so far # is to store the result in a temp file (the list_modules # uses a sub-perl process, so there is no way to pass a # filehandle or something similar). my $class = ref($self); require File::Temp; my $modules_fh = File::Temp->new; # list all the modules and place them in the output file my $src_app = $class->new( qw(--quiet exec --with), $src_perl, 'perl', '-MExtUtils::Installed', '-le', sprintf('BEGIN{@INC=grep {$_ ne q!.!} @INC}; open my $output_fh, ">", "%s"; print {$output_fh} $_ for ExtUtils::Installed->new->modules;', $modules_fh->filename ) ); $src_app->run; # here I should have the list of modules into the # temporary file name, so I can ask the destination # perl instance to install such list $modules_fh->close; open $modules_fh, '<', $modules_fh->filename; chomp(my @modules_to_install = <$modules_fh>); $modules_fh->close; die "\nNo modules installed on $src_perl !\n" if (! @modules_to_install); print "\nInstalling $#modules_to_install modules from $src_perl to $dst_perl ...\n"; # create a new application to 'exec' the 'cpanm' # with the specified module list my $app = $class->new( qw(--quiet exec --with), $dst_perl, 'cpanm', @modules_to_install ); $app->run; } sub format_info_output { my ($self, $module) = @_; my $out = ''; $out .= "Current perl:\n"; if ($self->current_perl) { $out .= " Name: " . $self->current_env . "\n"; $out .= " Path: " . $self->installed_perl_executable($self->current_perl) . "\n"; $out .= " Config: " . $self->configure_args($self->current_perl) . "\n"; $out .= join('', " Compiled at: ", (map { / Compiled at (.+)\n/ ? $1 : () } `@{[ $self->installed_perl_executable($self->current_perl) ]} -V`), "\n"); } else { $out .= "Using system perl." . "\n"; $out .= "Shebang: " . $self->system_perl_shebang . "\n"; } $out .= "\nperlbrew:\n"; $out .= " version: " . $self->VERSION . "\n"; $out .= " ENV:\n"; for(map{"PERLBREW_$_"}qw(ROOT HOME PATH MANPATH)) { $out .= " $_: " . ($self->env($_)||"") . "\n"; } if ($module) { my $code = qq{eval "require $module" and do { (my \$f = "$module") =~ s<::>g; \$f .= ".pm"; print "$module\n Location: \$INC{\$f}\n Version: " . ($module->VERSION ? $module->VERSION : "no VERSION specified" ) } or do { print "$module could not be found, is it installed?" } }; $out .= "\nModule: ".$self->do_capture($self->installed_perl_executable($self->current_perl), "-le", $code); } $out; } sub run_command_info { my ($self) = shift; print $self->format_info_output(@_); } sub BASHRC_CONTENT() { return "export PERLBREW_SHELLRC_VERSION=$VERSION\n" . (exists $ENV{PERLBREW_ROOT} ? "export PERLBREW_ROOT=$PERLBREW_ROOT\n" : "") . "\n" . <<'RC'; __perlbrew_reinit() { if [[ ! -d "$PERLBREW_HOME" ]]; then mkdir -p "$PERLBREW_HOME" fi [ -f "$PERLBREW_HOME/init" ] && rm "$PERLBREW_HOME/init" echo '# DO NOT EDIT THIS FILE' > "$PERLBREW_HOME/init" command perlbrew env $1 | \grep PERLBREW_ >> "$PERLBREW_HOME/init" . "$PERLBREW_HOME/init" __perlbrew_set_path } __perlbrew_purify () { local path patharray outsep IFS=: read -r${BASH_VERSION+a}${ZSH_VERSION+A} patharray <<< "$1" for path in "${patharray[@]}" ; do case "$path" in (*"$PERLBREW_HOME"*) ;; (*"$PERLBREW_ROOT"*) ;; (*) printf '%s' "$outsep$path" ; outsep=: ;; esac done } __perlbrew_set_path () { export MANPATH=$PERLBREW_MANPATH${PERLBREW_MANPATH:+:}$(__perlbrew_purify "$(manpath 2>/dev/null)") export PATH=${PERLBREW_PATH:-$PERLBREW_ROOT/bin}:$(__perlbrew_purify "$PATH") hash -r } __perlbrew_set_env() { local code code="$($perlbrew_command env $@)" || return $? eval "$code" } __perlbrew_activate() { [[ -n $(alias perl 2>/dev/null) ]] && unalias perl 2>/dev/null if [[ -n "$PERLBREW_PERL" ]]; then __perlbrew_set_env "$PERLBREW_PERL${PERLBREW_LIB:+@}$PERLBREW_LIB" fi __perlbrew_set_path } __perlbrew_deactivate() { __perlbrew_set_env unset PERLBREW_PERL unset PERLBREW_LIB __perlbrew_set_path } perlbrew () { local exit_status local short_option export SHELL if [[ $1 == -* ]]; then short_option=$1 shift else short_option="" fi case $1 in (use) if [[ -z "$2" ]] ; then echo -n "Currently using ${PERLBREW_PERL:-system perl}" [ -n "$PERLBREW_LIB" ] && echo -n "@$PERLBREW_LIB" echo else __perlbrew_set_env "$2" && { __perlbrew_set_path ; true ; } exit_status="$?" fi ;; (switch) if [[ -z "$2" ]] ; then command perlbrew switch else perlbrew use $2 && { __perlbrew_reinit $2 ; true ; } exit_status=$? fi ;; (off) __perlbrew_deactivate echo "perlbrew is turned off." ;; (switch-off) __perlbrew_deactivate __perlbrew_reinit echo "perlbrew is switched off." ;; (*) command perlbrew $short_option "$@" exit_status=$? ;; esac hash -r return ${exit_status:-0} } [[ -z "$PERLBREW_ROOT" ]] && export PERLBREW_ROOT="$HOME/perl5/perlbrew" [[ -z "$PERLBREW_HOME" ]] && export PERLBREW_HOME="$HOME/.perlbrew" if [[ ! -n "$PERLBREW_SKIP_INIT" ]]; then if [[ -f "$PERLBREW_HOME/init" ]]; then . "$PERLBREW_HOME/init" fi fi perlbrew_bin_path="${PERLBREW_ROOT}/bin" if [[ -f $perlbrew_bin_path/perlbrew ]]; then perlbrew_command="$perlbrew_bin_path/perlbrew" else perlbrew_command="perlbrew" fi unset perlbrew_bin_path __perlbrew_activate RC } sub BASH_COMPLETION_CONTENT() { return <<'COMPLETION'; if [[ -n ${ZSH_VERSION-} ]]; then autoload -U +X bashcompinit && bashcompinit fi export PERLBREW="command perlbrew" _perlbrew_compgen() { COMPREPLY=( $($PERLBREW compgen $COMP_CWORD ${COMP_WORDS[*]}) ) } complete -F _perlbrew_compgen perlbrew COMPLETION } sub PERLBREW_FISH_CONTENT { return "set -x PERLBREW_SHELLRC_VERSION $VERSION\n" . <<'END'; function __perlbrew_reinit if not test -d "$PERLBREW_HOME" mkdir -p "$PERLBREW_HOME" end echo '# DO NOT EDIT THIS FILE' > "$PERLBREW_HOME/init" command perlbrew env $argv[1] | \grep PERLBREW_ >> "$PERLBREW_HOME/init" __source_init __perlbrew_set_path end function __perlbrew_set_path 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);') if test -n "$PERLBREW_MANPATH" set -l PERLBREW_MANPATH $PERLBREW_MANPATH":" set -x MANPATH {$PERLBREW_MANPATH}{$MANPATH_WITHOUT_PERLBREW} else set -x MANPATH $MANPATH_WITHOUT_PERLBREW end set -l PATH_WITHOUT_PERLBREW (eval $perlbrew_command display-pristine-path | perl -pe'y/:/ /') # silencing stderr in case there's a non-existent path in $PATH (see GH#446) if test -n "$PERLBREW_PATH" set -x PERLBREW_PATH (echo $PERLBREW_PATH | perl -pe 'y/:/ /' ) eval set -x PATH $PERLBREW_PATH $PATH_WITHOUT_PERLBREW 2> /dev/null else eval set -x PATH $PERLBREW_ROOT/bin $PATH_WITHOUT_PERLBREW 2> /dev/null end end function __perlbrew_set_env set -l code (eval $perlbrew_command env $argv | perl -pe 's/^(export|setenv)/set -xg/; s/=/ /; s/^unset[env]*/set -eug/; s/$/;/; y/:/ /') if test -z "$code" return 0; else eval $code end end function __perlbrew_activate functions -e perl if test -n "$PERLBREW_PERL" if test -z "$PERLBREW_LIB" __perlbrew_set_env $PERLBREW_PERL else __perlbrew_set_env $PERLBREW_PERL@$PERLBREW_LIB end end __perlbrew_set_path end function __perlbrew_deactivate __perlbrew_set_env set -x PERLBREW_PERL set -x PERLBREW_LIB set -x PERLBREW_PATH __perlbrew_set_path end function perlbrew test -z "$argv" and echo " Usage: perlbrew [options] [arguments]" and echo " or: perlbrew help" and return 1 switch $argv[1] case use if test ( count $argv ) -eq 1 if test -z "$PERLBREW_PERL" echo "Currently using system perl" else echo "Currently using $PERLBREW_PERL" end else __perlbrew_set_env $argv[2] if test "$status" -eq 0 __perlbrew_set_path end end case switch if test ( count $argv ) -eq 1 command perlbrew switch else perlbrew use $argv[2] if test "$status" -eq 0 __perlbrew_reinit $argv[2] end end case off __perlbrew_deactivate echo "perlbrew is turned off." case switch-off __perlbrew_deactivate __perlbrew_reinit echo "perlbrew is switched off." case '*' command perlbrew $argv end end function __source_init perl -pe's/^(export|setenv)/set -xg/; s/=/ /; s/$/;/;' "$PERLBREW_HOME/init" | source end if test -z "$PERLBREW_ROOT" set -x PERLBREW_ROOT "$HOME/perl5/perlbrew" end if test -z "$PERLBREW_HOME" set -x PERLBREW_HOME "$HOME/.perlbrew" end if test -z "$PERLBREW_SKIP_INIT" -a -f "$PERLBREW_HOME/init" __source_init end set perlbrew_bin_path "$PERLBREW_ROOT/bin" if test -f "$perlbrew_bin_path/perlbrew" set perlbrew_command "$perlbrew_bin_path/perlbrew" else set perlbrew_command perlbrew end set -e perlbrew_bin_path __perlbrew_activate ## autocomplete stuff ############################################# function __fish_perlbrew_needs_command set cmd (commandline -opc) if test (count $cmd) -eq 1 -a $cmd[1] = 'perlbrew' return 0 end return 1 end function __fish_perlbrew_using_command set cmd (commandline -opc) if test (count $cmd) -gt 1 if [ $argv[1] = $cmd[2] ] return 0 end end end for com in (perlbrew help | perl -ne'print lc if s/^COMMAND:\s+//') complete -f -c perlbrew -n '__fish_perlbrew_needs_command' -a $com end for com in switch use; complete -f -c perlbrew -n "__fish_perlbrew_using_command $com" \ -a '(perlbrew list | perl -pe\'s/\*?\s*(\S+).*/$1/\')' end END } sub CSH_WRAPPER_CONTENT { return <<'WRAPPER'; set perlbrew_exit_status=0 if ( "$1" =~ -* ) then set perlbrew_short_option="$1" shift else set perlbrew_short_option="" endif switch ( "$1" ) case use: if ( $%2 == 0 ) then if ( $?PERLBREW_PERL == 0 ) then echo "Currently using system perl" else if ( $%PERLBREW_PERL == 0 ) then echo "Currently using system perl" else echo "Currently using $PERLBREW_PERL" endif endif else set perlbrew_line_count=0 foreach perlbrew_line ( "`\perlbrew env $2:q`" ) eval "$perlbrew_line" @ perlbrew_line_count++ end if ( $perlbrew_line_count == 0 ) then set perlbrew_exit_status=1 else source "$PERLBREW_ROOT/etc/csh_set_path" endif endif breaksw case switch: if ( $%2 == 0 ) then \perlbrew switch else perlbrew use "$2" && source "$PERLBREW_ROOT/etc/csh_reinit" "$2" endif breaksw case off: unsetenv PERLBREW_PERL foreach perlbrew_line ( "`\perlbrew env`" ) eval "$perlbrew_line" end source "$PERLBREW_ROOT/etc/csh_set_path" echo "perlbrew is turned off." breaksw case switch-off: unsetenv PERLBREW_PERL source "$PERLBREW_ROOT/etc/csh_reinit" '' echo "perlbrew is switched off." breaksw default: \perlbrew $perlbrew_short_option:q $argv:q set perlbrew_exit_status=$? breaksw endsw rehash exit $perlbrew_exit_status WRAPPER } sub CSH_REINIT_CONTENT { return <<'REINIT'; if ( ! -d "$PERLBREW_HOME" ) then mkdir -p "$PERLBREW_HOME" endif echo '# DO NOT EDIT THIS FILE' >! "$PERLBREW_HOME/init" \perlbrew env $1 >> "$PERLBREW_HOME/init" source "$PERLBREW_HOME/init" source "$PERLBREW_ROOT/etc/csh_set_path" REINIT } sub CSH_SET_PATH_CONTENT { return <<'SETPATH'; unalias perl if ( $?PERLBREW_PATH == 0 ) then setenv PERLBREW_PATH "$PERLBREW_ROOT/bin" endif setenv PATH_WITHOUT_PERLBREW `perl -e 'print join ":", grep { index($_, $ENV{PERLBREW_ROOT}) } split/:/,$ENV{PATH};'` setenv PATH "${PERLBREW_PATH}:${PATH_WITHOUT_PERLBREW}" setenv MANPATH_WITHOUT_PERLBREW `perl -e 'print join ":", grep { index($_, $ENV{PERLBREW_ROOT}) } split/:/,qx(manpath 2> /dev/null);'` if ( $?PERLBREW_MANPATH == 1 ) then setenv MANPATH ${PERLBREW_MANPATH}:${MANPATH_WITHOUT_PERLBREW} else setenv MANPATH ${MANPATH_WITHOUT_PERLBREW} endif SETPATH } sub CSHRC_CONTENT { return "setenv PERLBREW_SHELLRC_VERSION $VERSION\n\n" . <<'CSHRC'; if ( $?PERLBREW_HOME == 0 ) then setenv PERLBREW_HOME "$HOME/.perlbrew" endif if ( $?PERLBREW_ROOT == 0 ) then setenv PERLBREW_ROOT "$HOME/perl5/perlbrew" endif if ( $?PERLBREW_SKIP_INIT == 0 ) then if ( -f "$PERLBREW_HOME/init" ) then source "$PERLBREW_HOME/init" endif endif if ( $?PERLBREW_PATH == 0 ) then setenv PERLBREW_PATH "$PERLBREW_ROOT/bin" endif source "$PERLBREW_ROOT/etc/csh_set_path" alias perlbrew 'source "$PERLBREW_ROOT/etc/csh_wrapper"' CSHRC } sub append_log { my ($self, $message) = @_; my $log_handler; open($log_handler, '>>', $self->{log_file}) or die "Cannot open log file for appending: $!"; print $log_handler "$message\n"; close($log_handler); } sub INSTALLATION_FAILURE_MESSAGE { my ($self) = @_; return <{log_file} If some perl tests failed and you still want to install this distribution anyway, do: (cd $self->{dist_extracted_dir}; make install) You might also want to try upgrading patchperl before trying again: perlbrew install-patchperl Generally, if you need to install a perl distribution known to have minor test failures, do one of these commands to avoid seeing this message: perlbrew --notest install $self->{dist_name} perlbrew --force install $self->{dist_name} FAIL } 1; __END__ =encoding utf8 =head1 NAME App::perlbrew - Manage perl installations in your C<$HOME> =head2 SYNOPSIS # Installation curl -L https://install.perlbrew.pl | bash # Initialize perlbrew init # See what is available perlbrew available # Install some Perls perlbrew install 5.18.2 perlbrew install perl-5.8.1 perlbrew install perl-5.19.9 # See what were installed perlbrew list # Swith to an installation and set it as default perlbrew switch perl-5.18.2 # Temporarily use another version only in current shell. perlbrew use perl-5.8.1 perl -v # Or turn it off completely. Useful when you messed up too deep. # Or want to go back to the system Perl. perlbrew off # Use 'switch' command to turn it back on. perlbrew switch perl-5.12.2 # Exec something with all perlbrew-ed perls perlbrew exec -- perl -E 'say $]' =head2 DESCRIPTION L is a program to automate the building and installation of perl in an easy way. It provides multiple isolated perl environments, and a mechanism for you to switch between them. Everything are installed unter C<~/perl5/perlbrew>. You then need to include a bashrc/cshrc provided by perlbrew to tweak the PATH for you. You then can benefit from not having to run C commands to install cpan modules because those are installed inside your C too. For the documentation of perlbrew usage see L command on L, or by running C, or by visiting L. The following documentation features the API of C module, and may not be remotely close to what your want to read. =head2 INSTALLATION It is the simplest to use the perlbrew installer, just paste this statement to your terminal: curl -L https://install.perlbrew.pl | bash Or this one, if you have C (default on FreeBSD): fetch -o- https://install.perlbrew.pl | sh After that, C installs itself to C<~/perl5/perlbrew/bin>, and you should follow the instruction on screen to modify your shell rc file to put it in your PATH. The installed perlbrew command is a standalone executable that can be run with system perl. The minimum system perl version requirement is 5.8.0, which should be good enough for most of the OSes these days. A fat-packed version of L is also installed to C<~/perl5/perlbrew/bin>, which is required to build old perls. The directory C<~/perl5/perlbrew> will contain all install perl executables, libraries, documentations, lib, site_libs. In the documentation, that directory is referred as C. If you need to set it to somewhere else because, say, your C has limited quota, you can do that by setting C environment variable before running the installer: export PERLBREW_ROOT=/opt/perl5 curl -L https://install.perlbrew.pl | bash As a result, different users on the same machine can all share the same perlbrew root directory (although only original user that made the installation would have the permission to perform perl installations.) You may also install perlbrew from CPAN: cpan App::perlbrew In this case, the perlbrew command is installed as C or C or others, depending on the location of your system perl installation. Please make sure not to run this with one of the perls brewed with perlbrew. It's the best to turn perlbrew off before you run that, if you're upgrading. perlbrew off cpan App::perlbrew You should always use system cpan (like /usr/bin/cpan) to install C because it will be installed under a system PATH like C, which is not affected by perlbrew C or C command. The C command will not upgrade the perlbrew installed by cpan command, but it is also easy to upgrade perlbrew by running C again. =head2 METHODS =over 4 =item (Str) current_perl Return the "current perl" object attribute string, or, if absent, the value of C environment variable. =item (Str) current_perl (Str) Set the C object attribute to the given value. =back =head2 PROJECT DEVELOPMENT L uses github L and RT for issue tracking. Issues sent to these two systems will eventually be reviewed and handled. See L for a list of project contributors. =head1 AUTHOR Kang-min Liu C<< >> =head1 COPYRIGHT Copyright (c) 2010- Kang-min Liu C<< >>. =head3 LICENCE The MIT License =head2 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. =cut command-list.t000644000765000024 365613614277060 16521 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; BEGIN { delete $ENV{PERLBREW_HOME}; delete $ENV{PERLBREW_ROOT}; delete $ENV{PERLBREW_LIB}; } use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use File::Spec::Functions qw( catdir ); use Test::Spec; use Test::Output qw( stdout_like ); mock_perlbrew_install("perl-5.12.3"); mock_perlbrew_install("perl-5.12.4"); mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_install("perl-5.14.2"); { no warnings 'redefine'; sub App::perlbrew::current_perl { "perl-5.12.3" } } describe "list command," => sub { describe "when there no libs under PERLBREW_HOME,", sub { it "displays a list of perl installation names", sub { my $app = App::perlbrew->new("list"); stdout_like sub { $app->run(); }, qr/^(\s|\*)\sc?perl-?\d\.\d{1,3}[_.]\d{1,2}\s+/, 'Cannot find Perl in output' }; }; describe "when there are lib under PERLBREW_HOME,", sub { before each => sub { unless ( -d catdir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.12.3@nobita') ) { App::perlbrew->new("lib", "create", "nobita")->run; } unless ( -d catdir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.12.3@shizuka') ) { App::perlbrew->new("lib", "create", "shizuka")->run; } }; it "displays lib names" => sub { my $app = App::perlbrew->new("list"); stdout_like sub { $app->run(); }, qr/^(\s|\*)\sc?perl-?\d\.\d{1,3}[_.]\d{1,2}(@\w+)?/, 'Cannot find Perl with libraries in output' }; it "marks currently activated lib", sub { $ENV{PERLBREW_LIB} = "nobita"; my $app = App::perlbrew->new("list"); stdout_like sub { $app->run(); }, qr/^(\s|\*)\sc?perl-?\d\.\d{1,3}[_.]\d{1,2}(\@nobita)?/, 'Cannot find Perl with libraries in output' }; }; }; runtests unless caller; command-info.t000644000765000024 1320313614277060 16506 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Test::Output; use File::Spec; use Config; use App::perlbrew; describe "info command" => sub { it "should display info if under perlbrew perl" => sub { my $app = App::perlbrew->new("info"); my $mock_perl = { mock => 'current_perl' }; my $perl_path = $Config{perlpath}; $app->expects("current_perl")->returns($mock_perl)->at_least_once(); $app->expects("current_env")->returns('perl-5.8.9'); $app->expects("installed_perl_executable")->with($mock_perl)->returns($perl_path)->at_least_once(); $app->expects("configure_args")->with($mock_perl)->returns('config_args_value'); $app->expects("system_perl_shebang")->never; local $ENV{PERLBREW_ROOT} = 'perlbrew_root_value'; local $ENV{PERLBREW_HOME} = 'perlbrew_home_value'; local $ENV{PERLBREW_PATH} = 'perlbrew_path_value'; local $ENV{PERLBREW_MANPATH} = 'perlbrew_manpath_value'; my $expected = <<"OUT"; Current perl: Name: perl-5.8.9 Path: \Q$perl_path\E Config: config_args_value Compiled at: ...\\s+\\d{1,2}\\s+\\d{4}\\s+\\d{1,2}:\\d{2}:\\d{2} perlbrew: version: \Q$App::perlbrew::VERSION\E ENV: PERLBREW_ROOT: perlbrew_root_value PERLBREW_HOME: perlbrew_home_value PERLBREW_PATH: perlbrew_path_value PERLBREW_MANPATH: perlbrew_manpath_value OUT stdout_like sub { $app->run(); }, qr/$expected/; }; it "should display info if under system perl" => sub { my $app = App::perlbrew->new("info"); $app->expects("current_perl")->returns(''); $app->expects("current_env")->never; $app->expects("installed_perl_executable")->never; $app->expects("configure_args")->never; $app->expects("system_perl_shebang")->returns("system_perl_shebang_value")->once; local $ENV{PERLBREW_ROOT} = 'perlbrew_root_value'; local $ENV{PERLBREW_HOME} = 'perlbrew_home_value'; local $ENV{PERLBREW_PATH} = 'perlbrew_path_value'; local $ENV{PERLBREW_MANPATH} = 'perlbrew_manpath_value'; my $expected = <<"OUT"; Current perl: Using system perl. Shebang: system_perl_shebang_value perlbrew: version: \Q$App::perlbrew::VERSION\E ENV: PERLBREW_ROOT: perlbrew_root_value PERLBREW_HOME: perlbrew_home_value PERLBREW_PATH: perlbrew_path_value PERLBREW_MANPATH: perlbrew_manpath_value OUT stdout_like sub { $app->run(); }, qr/$expected/; }; it "should display info for a module if the module is installed" => sub { my $app = App::perlbrew->new; my $mock_perl = { mock => 'current_perl' }; my $perl_path = $Config{perlpath}; my $module_name = "Data::Dumper"; $app->expects("current_perl")->returns($mock_perl)->at_least_once(); $app->expects("current_env")->returns('perl-5.8.9'); $app->expects("installed_perl_executable")->with($mock_perl)->returns($perl_path)->at_least_once(); $app->expects("configure_args")->with($mock_perl)->returns('config_args_value'); $app->expects("system_perl_shebang")->never; local $ENV{PERLBREW_ROOT} = 'perlbrew_root_value'; local $ENV{PERLBREW_HOME} = 'perlbrew_home_value'; local $ENV{PERLBREW_PATH} = 'perlbrew_path_value'; local $ENV{PERLBREW_MANPATH} = 'perlbrew_manpath_value'; my $v = "KNOWN_VALUE"; (my $path_seperator = File::Spec->catdir( ( $v, $v ) ) ) =~ s/$v//g; my $module_location = join $path_seperator, split( /::/, $module_name); my $expected = <<"OUT"; Current perl: Name: perl-5.8.9 Path: \Q$perl_path\E Config: config_args_value Compiled at: ...\\s+\\d{1,2}\\s+\\d{4}\\s+\\d{1,2}:\\d{2}:\\d{2} perlbrew: version: \Q$App::perlbrew::VERSION\E ENV: PERLBREW_ROOT: perlbrew_root_value PERLBREW_HOME: perlbrew_home_value PERLBREW_PATH: perlbrew_path_value PERLBREW_MANPATH: perlbrew_manpath_value Module: \Q$module_name\E Location: .*\Q$module_location\E.pm Version: [\\d\\._]+ OUT stdout_like sub { $app->{args} = [ "info", $module_name]; $app->run(); }, qr/$expected/; }; it "should display a message that the module can't be found if the module isn't installed" => sub { my $app = App::perlbrew->new; my $mock_perl = { mock => 'current_perl' }; my $perl_path = $Config{perlpath}; my $module_name = "SOME_FAKE_MODULE"; $app->expects("current_perl")->returns($mock_perl)->at_least_once(); $app->expects("current_env")->returns('perl-5.8.9'); $app->expects("installed_perl_executable")->with($mock_perl)->returns($perl_path)->at_least_once(); $app->expects("configure_args")->with($mock_perl)->returns('config_args_value'); $app->expects("system_perl_shebang")->never; local $ENV{PERLBREW_ROOT} = 'perlbrew_root_value'; local $ENV{PERLBREW_HOME} = 'perlbrew_home_value'; local $ENV{PERLBREW_PATH} = 'perlbrew_path_value'; local $ENV{PERLBREW_MANPATH} = 'perlbrew_manpath_value'; my $expected = <<"OUT"; Current perl: Name: perl-5.8.9 Path: \Q$perl_path\E Config: config_args_value Compiled at: ...\\s+\\d{1,2}\\s+\\d{4}\\s+\\d{1,2}:\\d{2}:\\d{2} perlbrew: version: \Q$App::perlbrew::VERSION\E ENV: PERLBREW_ROOT: perlbrew_root_value PERLBREW_HOME: perlbrew_home_value PERLBREW_PATH: perlbrew_path_value PERLBREW_MANPATH: perlbrew_manpath_value Module: $module_name could not be found, is it installed?.* OUT stdout_like sub { $app->{args} = [ "info", $module_name]; $app->run(); }, qr/$expected/; }; }; runtests unless caller; installation-perlbrew.t000644000765000024 552413614277060 20447 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Capture::Tiny qw( capture_stdout ); note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; subtest "`perlbrew self-install` initialize the required dir structure under PERLBREW_ROOT", sub { my $app = App::perlbrew->new('--quiet', 'self-install'); $app->run; ok -d dir($ENV{PERLBREW_ROOT}, "bin"); ok -d dir($ENV{PERLBREW_ROOT}, "etc"); ok -d dir($ENV{PERLBREW_ROOT}, "perls"); ok -d dir($ENV{PERLBREW_ROOT}, "dists"); ok -d dir($ENV{PERLBREW_ROOT}, "build"); ok -f file($ENV{PERLBREW_ROOT}, "bin", "perlbrew"); ok -f file($ENV{PERLBREW_ROOT}, "etc", "bashrc"); ok -f file($ENV{PERLBREW_ROOT}, "etc", "cshrc"); ok -f file($ENV{PERLBREW_ROOT}, "etc", "csh_reinit"); ok -f file($ENV{PERLBREW_ROOT}, "etc", "csh_set_path"); ok -f file($ENV{PERLBREW_ROOT}, "etc", "csh_wrapper"); }; subtest "Works with bash", sub { if ($ENV{PERLBREW_SHELLRC_VERSION}) { plan skip_all => "PERLBREW_SHELLRC_VERSION is defined, thus this subtest makes little sense."; return; } my $out = capture_stdout { my $app = App::perlbrew->new('self-install'); $app->current_shell("bash"); $app->run; }; like($out, qr| export PERLBREW_HOME=\S+|); like($out, qr| source \S+/etc/bashrc|); }; subtest "Works with fish", sub { if ($ENV{PERLBREW_SHELLRC_VERSION}) { plan skip_all => "PERLBREW_SHELLRC_VERSION is defined, thus this subtest makes little sense."; return; } my $out = capture_stdout { my $app = App::perlbrew->new('self-install'); $app->current_shell("fish"); $app->run; }; like($out, qr| set -x PERLBREW_HOME \S+|); like($out, qr| . \S+/etc/perlbrew.fish|); }; subtest "Works with zsh", sub { if ($ENV{PERLBREW_SHELLRC_VERSION}) { plan skip_all => "PERLBREW_SHELLRC_VERSION is defined, thus this subtest makes little sense."; return; } my $out = capture_stdout { my $app = App::perlbrew->new('self-install'); $app->current_shell("zsh4"); $app->run; }; like($out, qr| export PERLBREW_HOME=\S+|); like($out, qr| source \S+/etc/bashrc|); }; subtest "Exports PERLBREW_HOME when needed", sub { if ($ENV{PERLBREW_SHELLRC_VERSION}) { plan skip_all => "PERLBREW_SHELLRC_VERSION is defined, thus this subtest makes little sense."; return; } my $out = capture_stdout { local $App::perlbrew::PERLBREW_HOME = App::Perlbrew::Path->new ($ENV{HOME}, ".perlbrew"); my $app = App::perlbrew->new('self-install'); $app->current_shell("bash"); $app->run; }; unlike($out, qr|PERLBREW_HOME=\S+|); like($out, qr| source \S+/etc/bashrc|); }; done_testing; config.yml000644000765000024 67113614277060 17277 0ustar00gugodstaff000000000000App-perlbrew-0.88/.circleciversion: 2 jobs: criticism: docker: - image: gugod/perlcritic:latest steps: - checkout - run: perlcritic --profile .perlcriticrc t lib script test: docker: - image: perl:5.28 steps: - checkout - run: perl -V - run: cpanm --notest Test2::Harness; cpanm --notest --installdeps . - run: yath workflows: version: 2 test_and_critic: jobs: - criticism - test 08.error_install_cpanm.t000644000765000024 62013614277060 20361 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Exception; no warnings 'redefine'; sub App::perlbrew::http_get { "" } throws_ok( sub { my $app = App::perlbrew->new("install-cpanm"); $app->run; }, qr[ERROR: Failed to retrieve cpanm executable.] ); done_testing; README.md000644000765000024 1403313614277060 14770 0ustar00gugodstaff000000000000App-perlbrew-0.88# NAME App::perlbrew - Manage perl installations in your `$HOME` ## SYNOPSIS # Installation curl -L https://install.perlbrew.pl | bash # Initialize perlbrew init # See what is available perlbrew available # Install some Perls perlbrew install 5.18.2 perlbrew install perl-5.8.1 perlbrew install perl-5.19.9 # See what were installed perlbrew list # Swith to an installation and set it as default perlbrew switch perl-5.18.2 # Temporarily use another version only in current shell. perlbrew use perl-5.8.1 perl -v # Or turn it off completely. Useful when you messed up too deep. # Or want to go back to the system Perl. perlbrew off # Use 'switch' command to turn it back on. perlbrew switch perl-5.12.2 # Exec something with all perlbrew-ed perls perlbrew exec -- perl -E 'say $]' ## DESCRIPTION [perlbrew](https://metacpan.org/pod/perlbrew) is a program to automate the building and installation of perl in an easy way. It provides multiple isolated perl environments, and a mechanism for you to switch between them. Everything are installed unter `~/perl5/perlbrew`. You then need to include a bashrc/cshrc provided by perlbrew to tweak the PATH for you. You then can benefit from not having to run `sudo` commands to install cpan modules because those are installed inside your `HOME` too. For the documentation of perlbrew usage see [perlbrew](https://metacpan.org/pod/perlbrew) command on [MetaCPAN](https://metacpan.org/), or by running `perlbrew help`, or by visiting [perlbrew's official website](https://perlbrew.pl/). The following documentation features the API of `App::perlbrew` module, and may not be remotely close to what your want to read. ## INSTALLATION It is the simplest to use the perlbrew installer, just paste this statement to your terminal: curl -L https://install.perlbrew.pl | bash Or this one, if you have `fetch` (default on FreeBSD): fetch -o- https://install.perlbrew.pl | sh After that, `perlbrew` installs itself to `~/perl5/perlbrew/bin`, and you should follow the instruction on screen to modify your shell rc file to put it in your PATH. The installed perlbrew command is a standalone executable that can be run with system perl. The minimum system perl version requirement is 5.8.0, which should be good enough for most of the OSes these days. A fat-packed version of [patchperl](https://metacpan.org/pod/patchperl) is also installed to `~/perl5/perlbrew/bin`, which is required to build old perls. The directory `~/perl5/perlbrew` will contain all install perl executables, libraries, documentations, lib, site\_libs. In the documentation, that directory is referred as `perlbrew root`. If you need to set it to somewhere else because, say, your `HOME` has limited quota, you can do that by setting `PERLBREW_ROOT` environment variable before running the installer: export PERLBREW_ROOT=/opt/perl5 curl -L https://install.perlbrew.pl | bash As a result, different users on the same machine can all share the same perlbrew root directory (although only original user that made the installation would have the permission to perform perl installations.) You may also install perlbrew from CPAN: cpan App::perlbrew In this case, the perlbrew command is installed as `/usr/bin/perlbrew` or `/usr/local/bin/perlbrew` or others, depending on the location of your system perl installation. Please make sure not to run this with one of the perls brewed with perlbrew. It's the best to turn perlbrew off before you run that, if you're upgrading. perlbrew off cpan App::perlbrew You should always use system cpan (like /usr/bin/cpan) to install `App::perlbrew` because it will be installed under a system PATH like `/usr/bin`, which is not affected by perlbrew `switch` or `use` command. The `self-upgrade` command will not upgrade the perlbrew installed by cpan command, but it is also easy to upgrade perlbrew by running `cpan App::perlbrew` again. ## METHODS - (Str) current\_perl Return the "current perl" object attribute string, or, if absent, the value of `PERLBREW_PERL` environment variable. - (Str) current\_perl (Str) Set the `current_perl` object attribute to the given value. ## PROJECT DEVELOPMENT [perlbrew project](https://perlbrew.pl/) uses github [https://github.com/gugod/App-perlbrew/issues](https://github.com/gugod/App-perlbrew/issues) and RT for issue tracking. Issues sent to these two systems will eventually be reviewed and handled. See [https://github.com/gugod/App-perlbrew/contributors](https://github.com/gugod/App-perlbrew/contributors) for a list of project contributors. # AUTHOR Kang-min Liu `` # COPYRIGHT Copyright (c) 2010- Kang-min Liu ``. ### LICENCE The MIT License ## DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 13.perl_release.t000644000765000024 301413614277060 17002 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; use CPAN::Perl::Releases; use JSON::PP qw(encode_json); describe "App::perlbrew#perl_release method" => sub { describe "given a valid perl version" => sub { it "returns the perl dist tarball file name, and its download url" => sub { my $app = App::perlbrew->new; for my $version (qw(5.14.2 5.10.1 5.10.0 5.004_05)) { my ($ball, $url) = $app->perl_release($version); like $ball, qr/perl-?${version}.tar.(bz2|gz)/; like $url, qr/${ball}$/; } }; }; describe "when the given versionis not found is CPAN::Perl::Releases" => sub { no warnings 'redefine'; my $version = "5.14.2"; my $orig_sub = \&CPAN::Perl::Releases::perl_tarballs; *App::perlbrew::http_get = sub { return encode_json({hits => {hits => [{_source => {download_url => "https://cpan.metacpan.org/authors/id/SOMEONE/perl-${version}.tar.gz"} }]}}); }; *CPAN::Perl::Releases::perl_tarballs = sub {}; my $app = App::perlbrew->new; my ($ball, $url) = $app->perl_release($version); like $ball, qr/^perl-?${version}.tar.(bz2|gz)$/, $ball; like $url, qr#^https?://cpan\.metacpan\.org/authors/id/SOMEONE/${ball}$#, $url; *CPAN::Perl::Releases::perl_tarballs = $orig_sub; }; }; runtests unless caller; 17.release-detail-cperl-remote.t000644000765000024 134413614277060 21624 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; unless ($ENV{TEST_LIVE}) { plan skip_all => 'These tests send HTTP requests. Set env TEST_LIVE=1 to really run them.'; } my $app = App::perlbrew->new(); my $rd = { type => "cperl", "version" => "5.27.1" }; $app->release_detail_cperl_remote("cperl-5.27.1", $rd); ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{tarball_url}, "https://github.com/perl11/cperl/archive/cperl-5.27.1.tar.gz"; is $rd->{tarball_name}, "cperl-5.27.1.tar.gz"; done_testing; 09.exit_status.t000644000765000024 110213614277060 16715 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Exception; use Path::Class; my $bin_perlbrew = file(__FILE__)->dirname->dirname->child("script")->child("perlbrew"); throws_ok( sub { my $app = App::perlbrew->new("unknown-command"); $app->run; }, qr[unknown-command] ); my $perl = $^X; system("$perl -Ilib ${bin_perlbrew} unknown-command 2>&1"); ok($? != 0); system("$perl -Ilib ${bin_perlbrew} version 2>&1"); ok($? == 0); done_testing; 18.release-detail-perl-remote.t000644000765000024 144013614277060 21457 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; unless ($ENV{TEST_LIVE}) { plan skip_all => 'These tests send HTTP requests. Set env TEST_LIVE=1 to really run them.'; } my $app = App::perlbrew->new(); $app->cpan_mirror("http://www.cpan.org"); my $rd = { type => "perl", "version" => "5.18.2" }; my ($error, undef) = $app->release_detail_perl_remote("perl-5.18.2", $rd); ok !$error; ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{tarball_url}, "http://www.cpan.org/src/5.0/perl-5.18.2.tar.bz2"; is $rd->{tarball_name}, "perl-5.18.2.tar.bz2"; done_testing; current_shell.t000644000765000024 151613614277060 16774 0ustar00gugodstaff000000000000App-perlbrew-0.88/tuse warnings; use strict; use Test::More tests => 6; use App::perlbrew; my $current_shell = (split("/", $ENV{SHELL}))[-1]; my $self = App::perlbrew->new(); is($self->current_shell(), $current_shell, 'current_shell gives the expected shell based on $SHELL environment variable') or diag("\$SHELL = $ENV{SHELL}"); is($self->current_shell('foobar'), 'foobar', 'current_shell setups and returns anything passed as parameter'); for my $shell (qw(bash zsh)) { note("Testing with $shell"); $self->current_shell($shell); ok($self->current_shell_is_bashish(), 'current_shell_is_bashish() returns true if the current shell is Bash or based on it'); } for my $shell (qw(ksh sh)) { note("Testing with $shell"); $self->current_shell($shell); is($self->current_shell_is_bashish(), 0, 'current_shell_is_bashish() returns false'); } LICENSE000644000765000024 224113614277060 14474 0ustar00gugodstaff000000000000App-perlbrew-0.88This software is Copyright (c) 2020 by Kang-min Liu C<< >>. This is free software, licensed under: The MIT (X11) License The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. command-exec.t000644000765000024 3145213614277060 16505 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::Spec; use Test::Output; mock_perlbrew_install("perl-5.12.3"); mock_perlbrew_install("perl-5.12.4"); mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_install("perl-5.14.2"); describe 'perlbrew exec perl -E "say 42"' => sub { it "invokes all perls" => sub { my $app = App::perlbrew->new(qw(exec perl -E), "say 42"); my @perls = $app->installed_perls; $app->expects("do_system_with_exit_code")->exactly(4)->returns( sub { my ($self, @args) = @_; is_deeply \@args, ["perl", "-E", "say 42"]; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); my $perl_installation = shift @perls; is $perlbrew_bin_path, App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "bin"); is $perlbrew_perl_bin_path, App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", $perl_installation->{name}, "bin"), "perls/". $perl_installation->{name} . "/bin"; return 0; } ); $app->run; }; }; describe 'perlbrew exec --with perl-5.12.3 perl -E "say 42"' => sub { it "invokes perl-5.12.3/bin/perl" => sub { my $app = App::perlbrew->new(qw(exec --with perl-5.12.3 perl -E), "say 42"); $app->expects("do_system_with_exit_code")->returns( sub { my ($self, @args) = @_; is_deeply \@args, ["perl", "-E", "say 42"]; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); is $perlbrew_bin_path, App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "bin"); is $perlbrew_perl_bin_path, App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.12.3", "bin"); return 0; } ); $app->run; }; }; describe 'perlbrew exec --with perl-5.14.1,perl-5.12.3,perl-5.14.2 perl -E "say 42"' => sub { it "invokes each perl in the specified order" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1 perl-5.12.3 perl-5.14.2", qw(perl -E), "say 42"); my @perl_paths; $app->expects("do_system_with_exit_code")->exactly(3)->returns( sub { my ($self, @args) = @_; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); push @perl_paths, $perlbrew_perl_bin_path; return 0; } ); $app->run; is_deeply \@perl_paths, [ App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.12.3", "bin"), App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.2", "bin"), ]; }; }; describe 'perlbrew exec --with perl-5.14.1,perl-foobarbaz, ' => sub { it "ignore the unrecognized 'perl-foobarbaz'" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1 perl-foobarbaz", qw(perl -E), "say 42"); my @perl_paths; $app->expects("do_system_with_exit_code")->returns( sub { my ($self, @args) = @_; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); push @perl_paths, $perlbrew_perl_bin_path; return 0; } ); $app->run; is_deeply \@perl_paths, [ App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), ]; }; }; describe 'perlbrew exec --with perl-5.14.1,5.14.1 ' => sub { it "exec 5.14.1 twice, since that is what is specified" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1 5.14.1", qw(perl -E), "say 42"); my @perl_paths; $app->expects("do_system_with_exit_code")->exactly(2)->returns( sub { my ($self, @args) = @_; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); push @perl_paths, $perlbrew_perl_bin_path; return 0; } ); $app->run; is_deeply \@perl_paths, [ App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), ]; }; }; describe 'exec exit code' => sub { describe "logging" => sub { it "should work" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1", qw(perl -E), "somesub 42"); $app->expects("format_info_output")->exactly(1)->returns("format_info_output_value\n"); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(7<<8); stderr_is sub { eval { $app->run; 1; }; }, <<"OUT"; Command [perl -E 'somesub 42'] terminated with exit code 7 (\$? = 1792) under the following perl environment: format_info_output_value OUT }; it "should be quiet if asked" => sub { my $app = App::perlbrew->new(qw(exec --quiet --with), "perl-5.14.1", qw(perl -E), "somesub 42"); $app->expects("format_info_output")->exactly(0)->returns('should not be called!'); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(7<<8); stderr_is sub { eval { $app->run; 1; }; }, ''; }; it "should format info output for right perl" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1", qw(perl -E), "somesub 42"); $app->expects("format_info_output")->exactly(1)->returns(sub { my ($self) = @_; is $self->current_env, 'perl-5.14.1'; like $self->installed_perl_executable('perl-5.14.1'), qr/perl-5.14.1/; "format_info_output_value\n"; }); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(7<<8); eval { $app->run; 1; }; }; }; describe "no halt-on-error" => sub { it "should exit with success code when several perls ran" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1 perl-5.14.1", qw(perl -E), "say 42"); App::perlbrew->expects("do_exit_with_error_code")->never; $app->expects("do_system_with_exit_code")->exactly(2)->returns(0); $app->run; }; it "should exit with error code " => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1", qw(perl -E), "say 42"); $app->expects("format_info_output")->exactly(1)->returns(''); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { my ($self, $code) = @_; is $code, 1; # exit with error, but don't propogate exact failure codes die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(3<<8); ok !eval { $app->run; 1; }; is $@, "simulate exit\n"; }; it "should exit with error code when several perls ran" => sub { my $app = App::perlbrew->new(qw(exec --with), "perl-5.14.1 perl-5.14.1", qw(perl -E), "say 42"); $app->expects("format_info_output")->exactly(1)->returns(''); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { my ($self, $code) = @_; is $code, 1; # exit with error, but don't propogate exact failure codes die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(sub { $app->expects("do_system_with_exit_code")->exactly(1)->returns(sub { # make sure second call to exec is made 0; # second call is success }); 3<<8; # first exec failed }); ok !eval { $app->run; 1; }; is $@, "simulate exit\n"; }; }; describe "halt-on-error" => sub { it "should exit with success code " => sub { my $app = App::perlbrew->new(qw(exec --halt-on-error --with), "perl-5.14.1", qw(perl -E), "say 42"); App::perlbrew->expects("do_exit_with_error_code")->never; $app->expects("do_system_with_exit_code")->exactly(1)->returns(0); $app->run; }; it "should exit with error code " => sub { my $app = App::perlbrew->new(qw(exec --halt-on-error --with), "perl-5.14.1", qw(perl -E), "say 42"); $app->expects("format_info_output")->exactly(1)->returns(''); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { my ($self, $code) = @_; is $code, 3; die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(3<<8); ok !eval { $app->run; 1; }; is $@, "simulate exit\n"; }; it "should exit with code 255 if program terminated with signal or something" => sub { my $app = App::perlbrew->new(qw(exec --halt-on-error --with), "perl-5.14.1", qw(perl -E), "say 42"); $app->expects("format_info_output")->exactly(1)->returns(''); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { my ($self, $code) = @_; is $code, 255; die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(-1); ok !eval { $app->run; 1; }; is $@, "simulate exit\n"; }; it "should exit with error code when several perls ran" => sub { my $app = App::perlbrew->new(qw(exec --halt-on-error --with), "perl-5.14.1 perl-5.14.1", qw(perl -E), "say 42"); $app->expects("format_info_output")->exactly(1)->returns(''); App::perlbrew->expects("do_exit_with_error_code")->exactly(1)->returns(sub { my ($self, $code) = @_; is $code, 7; die "simulate exit\n"; }); $app->expects("do_system_with_exit_code")->exactly(1)->returns(sub { $app->expects("do_system_with_exit_code")->exactly(1)->returns(sub { 7<<8; }); 0; }); ok !eval { $app->run; 1; }; is $@, "simulate exit\n"; }; }; }; describe "minimal perl version" => sub { it "only executes the needed version" => sub { my @perl_paths; my $app = App::perlbrew->new(qw(exec --min 5.014), qw(perl -E), "say 42"); $app->expects("do_system_with_exit_code")->exactly(2)->returns(sub { my ($self, @args) = @_; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); push @perl_paths, $perlbrew_perl_bin_path; return 0; }); $app->run; # Don't care about the order, just the fact all of them were visited is_deeply [sort @perl_paths], [sort ( App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.2", "bin"), App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), )]; }; }; describe "maximum perl version" => sub { it "only executes the needed version" => sub { my @perl_paths; my $app = App::perlbrew->new(qw(exec --max 5.014), qw(perl -E), "say 42"); $app->expects("do_system_with_exit_code")->exactly(2)->returns(sub { my ($self, @args) = @_; my ($perlbrew_bin_path, $perlbrew_perl_bin_path, @paths) = split(":", $ENV{PATH}); push @perl_paths, $perlbrew_perl_bin_path; return 0; }); $app->run; # Don't care about the order, just the fact all of them were visited is_deeply [sort @perl_paths], [sort ( App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.12.4", "bin"), App::Perlbrew::Path->new($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.12.3", "bin"), )]; }; }; runtests unless caller; Changes000644000765000024 5365013614277060 15014 0ustar00gugodstaff000000000000App-perlbrew-0.880.88 - Released at 2020-01-29T21:40:07+0900 - Thanks to our contributors: Dave Rolsky, Gil Magno, Zhu Sheng Li - `install` command now shows errors message from http_downlod. Github PR #681. - Fix: The .tar.bz2 suffix are removed from the output ouf `available` PR #685 0.87 - Released at 2019-10-25T22:55:40+0900 - Thanks to our contributors: Branislav Zahradník, Christopher Chavez, Jon Jacobson, Konstantin S. Uvarin, Pali, Shoichi Kaji, Tomasz Konojacki, jkjacobson, rage311 - Use the new official repo url for fetching perl blead. Github issue #677 - Add `--min` and `--max` options to `exec` command. Github PR #656 - Fix "ERROR: Cannot find the tarball for perl-$version". Github PR #669 - Fix calling patchperl on readonly files. Github PR #674 - Fix installation from local tarbal files. See https://rt.cpan.org/Ticket/Display.html?id=129871 - Internal refactoring. Github PR #667, #662 - Various corrections of documentation. Github PR #676, #660 0.86 - Released at 2019-01-19T09:39:55+0900 - Thanks to our contributors: Olaf Alders, Paul Cochrane - Fix an error from 'install' command. https://rt.cpan.org/Public/Bug/Display.html?id=128083 - Tweak the separater characters of 'exec' command: See https://github.com/gugod/App-perlbrew/issues/648 0.85 - Released at 2018-12-15T23:24:15+0900 - Thanks to our contributors: Branislav Zahradník, Guido Flohr, Joelle Maslak, Luca Ferrari, rage311 - Fix the behaviour of 'clone-modules' - Various internal refactoring 0.84 - Released at 2018-06-24T08:26:14+0900 - Thanks to our contributors: Joelle Maslak - Unbreak 'available' command after some updates from cpan.org web site. - Unbreak the installation -- which missed "perlbrew" command due to a mistake when using mbtiny. 0.83 - Released at 2018-05-30T08:04:43+0900 - Thanks to our contributors: Alceu Rodrigues de Freitas Junior, Dan Book, Luca Ferrari, María Inés Parnisari, Mohammad S Anwar, Shoichi Kaji, sylints - my respect to search.cpan.org - MAKE env var can now be used to specify the "make" program. - New command: install-cpm - "install" command now has a "--builddir" option for specifying a work directory - "list" command now takes "--verbose" option. - "clone-modules" command is now better documented. 0.82 - Released at 2017-12-17T09:53:00+0900 - Thanks to our contributors: Alceu Rodrigues de Freitas Junior, Paul Cochrane - Fix regression of 'perlbrew install blead' 0.81 - Released at 2017-12-09T15:12:04+0900 - Thanks to our contributors: Luca Ferrari, Zac Bentley, perlancar, Nicolas R, gregor herrmann, Paul Cochrane - New command: clone-modules - Recognize tarball in .tar.xz extension - The output of "availables" is now sorted by versions - Unbreak the integration with cperl releases - Make `perlbrew install` runs correctly on AIX - support the current perl blead (5.28) 0.80 - Released at 2017-06-30T07:40:45+0200 - Fix version in META.yml in CPAN distribution. See: https://rt.cpan.org/Public/Bug/Display.html?id=122279 0.79 - Released at 2017-06-25T23:40:45+0200 - deal with perl-5.26 change about @INC in Makefile.PL - "available" command now also shows the URLs 0.78 - Released at 2016-11-20T22:59:55+0100 - Thanks to our contributors: Manuel Streuhofer, Sergey Aleynikov - More fixes to accomodate changes on perl5.git.perl.org 0.77 - Released at 2016-11-12T06:42:45+0100 - Thanks to our contributors: Dennis Kaarsemaker, Roel Harbers - The "uninstall" command now requires confirmation. - Fix bug with csh when PATH entries contain spaces - Accommodate git commit abbrivation changes on perl5.git.perl.org. See GH #524 https://github.com/gugod/App-perlbrew/pull/524 0.76 - Released at 2016-06-21T23:02:44+0200 - Start supporting cperl installation. - cperl releases are sourced from: https://github.com/perl11/cperl/releases - Deal with a regex warning when testing perlbrew with perl-5.25. See RT: https://rt.cpan.org/Ticket/Display.html?id=114871 0.75 - Released at 2016-03-16T23:41:41+0100 - Thanks to our contributors: Dave Cross, Dean Hamstead, Mark J. Reed, Mohammed El-Afifi, - Add '--no-patchperl' install option for skip running patchperl. - Add '--destdir' install option. - "uninstall" command now also delete associated libs. - "mirror" command is removed. - "config" command is removed. 0.74 - Released at 2015-11-24T20:55:02+0100 - A big thanks for our contributers: Aristotle Pagaltzis, Dave Jacoby, Dylan Cali, John Krull, Kevin Johnson, Nathan Day, Paul Cochrane, Tudor Constantin, Yanick Champoux, tm604 - support PERLBREW_LIB_PREFIX. https://github.com/gugod/App-perlbrew/commit/c29813cd4633683bd049964178a9ac96647986bc - prefer https and remove insecure download cli flags. https://github.com/gugod/App-perlbrew/commit/f49a908c1702942006de4654107edf77a48ead52 - perlbrew now dies when switching to/use a lib that does not exist. https://github.com/gugod/App-perlbrew/issues/432 - RHEL vendorlib fix https://github.com/gugod/App-perlbrew/issues/409 - improvements with fish integration. - unbreak when running with perl 5.14 or earlier: "list" command now correctly display lib names. - retaining flags in upgrade-perl. https://github.com/gugod/App-perlbrew/commit/b8d466670bbfc8e214a9d3ff2e889a4860060d84 - variour document clean up and improvements. 0.73 - Released at 2015-02-01T09:59:45+0100 - fixes and improvements from Manuel Streuhofer, Aristotle Pagaltzis, Sebastian Willert, David Hand, Eric Enns, Peter Roberts, Thomas Sibley, Ivan Baidakou, thanks! - fix 'perlbrew user' for fish users https://github.com/gugod/App-perlbrew/pull/429 - fix sub-shell for bash users https://github.com/gugod/App-perlbrew/pull/435 - clarify the 'perlbrew use' output: https://github.com/gugod/App-perlbrew/issues/439 0.72 - Released at 2014-10-27T21:38:19+0100 - Fix 0.71 breakage on MacOSX when the shell is bash or zsh - Fix spelling mistake. by @gregoa++ 0.71 - Released at 2014-09-13T19:59:15+0200 - Fix a few bugs of having unwanted values in PERL5LIB when switching between libs 0.70 - Released at 2014-09-02T20:41:15+0900 - download the fatpacked perlbrew from an http:// url. - protect fatpacked perlbrew from PERL5LIB, thanks to dagolden++ - avoid several warnings, thanks to DabeDotCom++ - making perlbrew a bit friendlier to init.d script, thanks to maxhq++ . see also https://github.com/gugod/App-perlbrew/pull/404 - make it possible to override PERLBREWURL before invoking installers 0.69 - Released at 2014-06-10T23:32:05+0200 - fix 'perlbrew env' breakage by just avoiding bad local::lib versions. 0.68 - Released at 2014-06-07T15:08:00+0200 - disable SSL cert checks. GH #385. - "perlbrew download stable" works as on expects. GH #383 - Many fish shell fixes. GH #376 #378 #379 - make 5.21 installable. GH #396 - various documentation fixes. 0.67 - Released at 2013-11-20T08:40:52+0100 - Support fish shell. Thanks to @yenzie++ - `info` command now takes an optional module name and show information for it. Thanks to @trcjr++ - doc/bug fixes from @mmcclimon++, @mperry2++, and markstos++ 0.66 - Released at 2013-08-03T00:22:29+0200 - fix a bug the made download failed with curl program. 0.65 - Released at 2013-08-01T07:19:03+0200 - exec command: error hadndling improvements. Thanks to @vsespb. - install command: add "--clang" option. Thanks to @salva - various bug fixes. thanks to @ironcamel and @gottreu 0.64 - Released at 2013-06-02T09:44:59+0200 - The build directory is removed before a new build. - New command: `install-multiple` - `clean` command now also removes tarballs - `install` command has many extra convienent flags. - Use "http://www.cpan.org" as the default CPAN mirror instead of "http://search.cpan.org/CPAN" - Remove the --insecure/--no-check-certificate command bflags when invoking curl/wget. 0.63 - Released at 2013-05-06T16:53:48+0200 - Remove `install-ack` command. - Due to the new architecture of ack2, it does not make sense to install the standalone executable anymore. Thus it's better not to do the installation with perlbrew. - Fix the `use` and `switch` command when switching between binary incompatible perl installations. See GH #297 0.62 - Released at 2013-04-07T17:43:58+0800 - Fix `list-modules` under lib env. It lists all modules in the lib, and in the base. - Use the original grep command to prevent aliases from breaking the content of init. GH #307 - `perlbrew alias help` is now the same as `perlbrew help alias` - `perlbrew exec --with ...` now preserve the order of specified names. 0.61 - Fix bashrc on various OS/shell. See GH #302 0.60 - Released at 2013-03-17T21:44:12+0100 - Exit status handling in bash function. See ed29288ab50a15d7df86d69cfcbddf108674eb07 for more details. - Fix compatibility with recent local::lib version. - Delay the loading of server modules. - Fix warnings when runing `perlbrew off` 0.59 - Released at 2013-02-17T12:34:10+0100 - New feature: "perlbrew install --switch $perl" - New feature: "perlbrew install stable" - Fix "--quiet" options for "exec" command - Fix mulitple test failures and warnings 0.58 - Released at 2012-11-16T08:45:18+0100 - Fix infinite re-exec loop as identified in #263 - Fix a case where PERL5LIB still contains previous entries after deactivating or activating other ones. 0.57 - Released at 2012-11-13T19:57:03+0100 - Fix an infinite re-exec loop 0.56 - Released at 2012-11-11T23:10:30+0100 - Fix GH #261, which breaks `off` and `swich-off` commands. 0.55 - Revert the requirement of 5.8.8. Now require 5.8 - Add PERLBREW_CPAN_MIRROR environment variable - Deal with a minor local::lib path problem. See GH #254. 0.54 - Released at 2012-10-24T21:21:25+0200 - Now requires perl 5.8.8 - Fix an issue with list-module command listing extra modules See GH #245 - Tweak default Configure options for pre-5.6 versions - Fix an issue with warning messagse in 'upgrade-perl' command. 0.53 - Released at 2012-10-14T17:41:17+0200 - New command: `info`. - requires CPAN::Perl::Releases 0.76 for 5.14.3 info. - Skip "." in @INC to deal with a `list-module` issue. GH #245. - Environment variable cleanups and minor bashrc rewrite. 0.52 - Released at 2012-10-04T21:30:40+0200 - userelocatableinc is no longer default. Meanwhile PERLBREW_CONFIGURE_FLAGS can still be used. - Fix GH #197 again. Also make sure perlbrew-unrelated PERL5LIB values are preserved. - Fix an issue that MANPATH contains unwanted values even after switch/use/off. 0.51 - Released at 2012-09-29T09:17:14+0200 - Fix a start-up warning message from bashrc when perlbrew is not active - Fix a breakage on CentOS due to the use of `manpath` command. 0.50 - Released at 2012-09-01T11:25:41+0200 - properly remove perlbrew-related PERL5LIB entries. GH #197 - minor documentation tweak. 0.49 - Released at 2012-08-25T22:32:22+0200 - Fix the build for perl-5.12 and 5.14 -- userelocatableinc are not working properly. https://github.com/gugod/App-perlbrew/issues/232 0.48 - Released at 2012-08-24T07:07:52+0200 - The build log output "build.log" is now named after the installation name for easier reference. - Fix the invokation configure command to actually contains -Duserelocatableinc - Experimental: bash/zsh users may put this to shell init instead: eval "$(~/perl5/perlbrew/bin/perlbrew init -)" - A few output message updates 0.47 - Released at 2012-08-23T07:59:53+0200 - New command: download. - New env var: PERLBREW_CONFIGURE_FLAGS - userelocatableinc is enabled by default when the installing perl version is greater than or equals to 5.8.9. It should make some use cases easier. In particular, you can move PERLBREW_ROOT directory to another place. - fix https://github.com/gugod/App-perlbrew/issues/216 for bash users and zsh users 0.46 - fix: The deprecation warning when running `self-upgrde` - fix: system MANPATH detection - improvement: Specifying multiple perl: `exec --with perl-5.14.2,perl-5.16.0` 0.45 - New command: install-ack . This install the standalone version of ack under $PERLBREW_ROOT/bin - New command: list-modules - `exec` command now also iterates thourgh all the libs - Documented the `--with` argument of exec command. See `perlbrew help exec` 0.44 - Notice: "self-install" command now alters the shebang to use system perl - Notice: "install-patchperl" command now alters the shebang to use system perl. - some documentation tweaks - fix: `perlbrew use` to/from a lib has not been working properly. 0.43 - cpantester-error fixes - csh support. Big thanks to matzsoft. - support 'fetch' command on FreeBSD. - Fix a bug that perlbrew failed to resolve version number when dist path contain "perl5" 0.42 - Improvement: die when running perlbrew (use|switch) with unknown installation name. - clean 'build.log' on install. ref: RT #69168. 0.41 - Fix installation issue when the specified version is not listed in CPAN::Perl::Releases - Fix sub-shell invocation for 'switch' and 'use' command. This is particularly for csh users, but it should also work for bash users. 0.40 - Make the stanalone perlbrew program smaller by using Perl::Strip - use CPAN::Perl::Releases to decide the location of perl tarball -- less HTTP hits - Prefer $PERLBREW_ROOT/bin/patchperl if it is there. 0.39 - Fix GH #179. lib naming are more consistent. - Fix GH #171. bash users are suggestted to upgrad to this version. - Fix GH #152. 0.38 - fix deps 0.37 - fix ENV mess after switching to diffirent libs multiple times - add --sitecustomize option 0.36 - fix test errors on freebsd that makes it uninstallable 0.35 - fixes for cpantester failures - requiers local::lib version 1.008 0.34 - Fix: remove duplicated items from the output of `perlbrew list`. - New Command: self-install. - This is actually renamed from an undocumented command `install-perlbrew` - Plus it gets documented. - Provide aditional bash completion control helper commands. - Documentation fixes / typo corrections. - alter MANPATHs, see GH #173 - Allow the representation like '@lib' te mean "a lib name under current perl.". See GH #153 0.33 - Remove Text::Levenshtein from the standalone executable. - Rearrange documentation so all perlbrew command usage document can be found in `perldoc perlbrew` - In the future, App::perlbrew POD should only contain the API doc for the module. 0.32 - A hotfix release: local::lib was not bundled in the previous release. 0.31 - NOTICE: Remove $PERLBREW_ROOT/Conf.pm if it's there, and re-run `perlbrew mirror` - perlbrew help system is changing. `perlbrew help ` now displays brief documentation for the command. - Add a global `--root` argument for all commands that can be used as a quick alternative to set PERLBREW_ROOT env var. - Avoid display paths to external/system perl in the output of `perlbrew list` - Replace Text::Levenshtein with a minimal implementation -- the standalone executable get to be smaller. 0.30 - New command: lib - local::lib integration is done with this command. - New command: install-patchperl - skip runs of 'exec' on aliases https://github.com/gugod/App-perlbrew/pull/135 - Respect -f flag when installing to replace an already installed perl. - Redefine the default value of -q flag to be false, and define it's meaning to be "complete silent" 0.29 - The installer now honors $TMPDIR (RT #70850) - Fixd GH #108. `perlbrew use` has a fallback for users that does not use bash/csh -compitable shell. - Deprecate the command 'perlbrew use system' simply use 'perlbrew off' or 'perlbrew switch-off' instead. - Deprecate the special case of `perlbrew use /path/to/bin/perl` and `perlbrew switch /path/to/bin/perl - perlbrew no longer cast magic to external perls. But there will be an alternative. 0.28 - fixes for cpantester - Fix 'switch' and 'use' for bash users, by Woody2143++ - The standalone `perlbrew` file is now packed with fatpacker, by running `dev-bin/build.sh`. `perl Makefile.PL` does no trigger a re-build anymore. - Update the installer to grab patchperl 0.46 0.27 - Hotfix for `perlbrew install` command 0.26 - Fix GH #119 - Fix t/08.exit_status.t for cpantesters - Fix several bugs in `exec` command - Implement GH #103 - install -v shows build.log - Add -Dusedevel when installing blead perl 0.25 - suggest when user types wrong commands. hoelzro++ - Improvements about self-upgrade by hoelzro++ - exit with non-zero status code when there's some sort of error. by punytan++ - Added verification of existing alias before attempting unalias. johncm++ - Fix `install-cpanm` for due to a recenet github cert update. kanetann++ 0.24 - Done GH #92 -- Show error messages on network errors. - Fix GH #82 -- deduplicate items in PATH for the `list` command. - Tests for various commands and methods. 0.23 - dependency fixes - Fix auto-detection of curl - Support OpenBSD pdksh. The provided bashrc should be compatible with pdksh. - Small improvement of 'exec' command. `perlbrew exec perl -v` now works. 0.22 - Fix ccache support on Linux with bash.. GH #87. - `install` command no longer clobbers existing installations. - New commands: uninstall, alias, self-upgrade - See more on http://perlbrew.pl/Release-0.22.html 0.21 - oylenshpeegul++ Let version numbers alone mean installation names. For example, 5.12.3 means perl-5.12.3 - audreyt++ fixed `perlbrew install ` that might installs to a wrong path. - Fix RT #68241 - Improve `perlbrew list` command output - Improve `perlbrew install` command. Now it takes a local .tar.gz filename - See more detail in http://perlbrew.pl/Release-0.21.html 0.20 - For more detail release note, see https://github.com/gugod/App-perlbrew/wiki/Relesae-0.20 - doherty++ FIX: stop when user specified an invalid perl version that cannot be found on cpan. - doherty++ specialized version installation: perlbrew install perl-blead / - am0c++ FIX: `perlbrew intsall /path/to/git/src/dir` 0.19 - Auto run 'perlbrew init' after an install (or upgrade) - Symlink dev versions of executables. For example,'perl5.13.11' to 'perl', 'prove5.13.11' to 'prove'. - Automatically apply patches necessary to make older perls build again on modern platforms with the help of Devel::PatchPerl. - A command "perlbrew available" to list recently available perls to build by trcjr 0.18 - Spotted and fixed by chad.a.davis++, an issue when bash set "noclobber" option, which breaks the creation of ~/.perlbrew/init. See https://rt.cpan.org/Ticket/Display.html?id=66518 - A simple `perlbrew clean` command to clean build dir. - delegate `-j` arg value to `make test_harness`. by dagolden++ - $HOME is replaced with "~" in many messages. https://rt.cpan.org/Ticket/Display.html?id=57668 0.17 - UPDATE NOTES: you need to init, off and switch back to the version you want; - Fix "perlbrew use" to work even if we are switched to a specific version - Fix "perlbrew env" to use current version, sets PERLBREW_PERL and proper PATH - Feature: "perlbrew use" shows current version in use - Feature: "perlbrew switch /path/to/special/perl name-of-special-perl" names for adhoc perl's - 'perlbrew exec' now excludes those non-brewed perl by frankcuny++ according to the discussion here: https://github.com/gugod/App-perlbrew/pull/43 0.16 - Use 'test_harness' for perl >= 5.7.3. avar++ - Use gtar on Solaris - RT #61042. doherty++ - Fix "perlbrew -f switch" by dalinaum++ 0.15 - DEPRECATE and REMOVE 'perlbrew installed' command. - Intrudoce a 'perlbrew exec' command - 'perlbrew use system' can be used to locally turn off perlbrew. yibe++ 0.14 - DEPRECATE `get_current_perl` function. Use `current_perl` instead - Show versions of non-perlbrew perls in the output of `perlbrew list`. Thanks to trcjr++ - bashrc fixes from yibe++ - Let help, -h and --help do the same thing -- showing full pod. 0.13 - 'installed' command is renamed to 'list', and will be deprecated soon. - Requires curl or wget from now -- to fetch https URLs. polettix++ 0.12 - Fix: missing init file generation. 0.11 - Avoid warning messages. Thanks Anno Siegel for the bug report and patch. - `-A` arguments are passed thru, thanks to gfx++. - Unbreak tests for older perls with older Test::Simple. Thanks to zaphod42++ - Better bash Integration, no more 'hash -r' - New command for bash and zsh: 'perlbrew use' - Deprecating 'installed'. use 'list' instead. 0.10 - Use File::Path::Tiny to avoid the api incompatibility of File::Path. - yanick++ and castaway++ fixes docmentation - gfx++ made it accept -Dopt style flags as Perl Configurate does. - (Danijel Tasov)++ added '-n' option -- no test! - xsawyerx++ fixes RT #57672, #60123, and GH #9 - Fixes #59729 0.09 - Use the proxy set in $ENV{http_proxy} if available. - Bypasses '-U' option to to configure. Thanks to chromatic++ 0.08 - Conf file + CPAN mirror support - Strip invalid dependency lines out of the makefile in older perl versions, to make them work with newer gcc versions - Add rudimentary pure-perl introspection, jrockway++ - Documentation, castaway++ 0.07 - Document about PERLBREW_ROOT and the issue installing it with CPAN. - Handle an edge case whn the tarball is not found on the http server. Thanks to sekimura++ - Improves 'switch' and 'off' command message. Thanks to Justin Davis. - PERL5OPT PERL5LIB are removed while configuring and testing a new perl. Thanks to Andrew Rodland. - fix a expression precedence bug. Thanks to Jesse Luehrs. 0.06 - Fix -as option. Thanks to doy++ and jasonmay++ 0.05 - Now it brews from git. jasonmay++ - Fix the uses of mkpath on various versions of perls. - Support the building of 5.13, and future developement versions 0.04 - Use File::Path::mkpath instead of make_path to make in runnable with older versions of Perl - a few document typo fixes. 0.03 - Fixed a bug that switch fail after 'off' 0.02 - Officially prepare a standalone program for quick download. - license changed to "Same as Perl" due to the fact HTTP::Lite is included - The 'installed' command now also lists all the 'perl' found in your PATH - The 'switch' command can take an executable like /usr/bin/perl - Various program options by Chris Prather - Fixes from Tatsuhiko Miyagawa 0.01 - First release. Installs perl-5.11.[12345] on my mac. Installation.pm000644000765000024 52713614277060 22417 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/App/Perlbrew/Path use strict; use warnings; package App::Perlbrew::Path::Installation; require App::Perlbrew::Path; our @ISA = qw( App::Perlbrew::Path ); sub name { $_[0]->basename; } sub bin { shift->child (bin => @_); } sub man { shift->child (man => @_); } sub perl { shift->bin ('perl'); } sub version_file { shift->child ('.version'); } 1; 16.release-detail.t000644000765000024 236113614277060 17227 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; subtest 'parse "perl-5.18.2"' => sub { my $app = App::perlbrew->new(); my $rd = $app->release_detail("perl-5.18.2"); ok defined( $rd->{type} ); ok defined( $rd->{version} ); ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{type}, "perl"; is $rd->{version}, "5.18.2"; }; subtest 'parse "5.18.2"' => sub { my $app = App::perlbrew->new(); my $rd = $app->release_detail("5.18.2"); ok defined( $rd->{type} ); ok defined( $rd->{version} ); ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{type}, "perl"; is $rd->{version}, "5.18.2"; }; subtest 'parse "cperl-5.22.2"' => sub { my $app = App::perlbrew->new(); my $rd = $app->release_detail("cperl-5.22.2"); ok defined( $rd->{type} ); ok defined( $rd->{version} ); ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{type}, "cperl"; is $rd->{version}, "5.22.2"; }; done_testing; 11.root_from_arg.t000644000765000024 416013614277060 17200 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use File::Temp qw(tempdir); use Test::Deep qw[]; use Test::Spec; sub looks_like_perlbrew_root; local $App::perlbrew::PERLBREW_ROOT = '/perlbrew/root'; local $ENV{PERLBREW_ROOT} = '/env/root'; local $ENV{HOME} = '/home'; describe "App::perlbrew#root method" => sub { it "should return \$App::perlbrew::PERLBREW_ROOT if provided" => sub { my $app = App::perlbrew->new; looks_like_perlbrew_root $app->root, '/perlbrew/root'; }; it "should default to \$ENV{PERLBREW_ROOT} if provided" => sub { local $App::perlbrew::PERLBREW_ROOT; my $app = App::perlbrew->new; looks_like_perlbrew_root $app->root, '/env/root'; }; it "should default to \$ENV{HOME} subpath" => sub { local $App::perlbrew::PERLBREW_ROOT; local $ENV{PERLBREW_ROOT}; my $app = App::perlbrew->new; looks_like_perlbrew_root $app->root, '/home/perl5/perlbrew'; }; it "should return the instance property of 'root' if set" => sub { my $app = App::perlbrew->new; $app->root("/fnord"); looks_like_perlbrew_root $app->root, "/fnord"; }; }; describe "App::perlbrew->new" => sub { it "should accept --root args and treat it as the value of PERLBREW_ROOT for the instance" => sub { my $temp_perlbrew_root = tempdir( CLEANUP => 1); my $app = App::perlbrew->new("--root" => $temp_perlbrew_root); looks_like_perlbrew_root $app->root, $temp_perlbrew_root; }; }; runtests unless caller; sub looks_like_perlbrew_root { my ($got, $expected) = @_; my ($ok, $stack); ($ok, $stack) = Test::Deep::cmp_details "$got", "$expected"; unless ($ok) { fail; diag "Return value comparison failed"; diag Test::Deep::deep_diag $stack; return; } ($ok, $stack) = Test::Deep::cmp_details "$got", "$App::perlbrew::PERLBREW_ROOT"; unless ($ok) { fail; diag "Global \$PERLBREW_ROOT comparison failed"; diag Test::Deep::deep_diag $stack; return; } return Test::Deep::cmp_deeply $got, Isa ('App::Perlbrew::Path::Root'); } 03.test_get_available_versions.t000644000765000024 30366613614277060 22165 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::More; use App::perlbrew; { no warnings 'redefine'; my $html_cpan = read_cpan_html(); my $html_metacpan = read_metacpan_html(); sub App::perlbrew::http_get { my $url = shift; if ($url =~ m/www\.cpan\.org/) { return $html_cpan; } elsif ($url =~ m/fastapi\.metacpan\.org/) { return $html_metacpan; } else { return ''; } } } plan tests => 17; my $app = App::perlbrew->new(); my @vers = $app->available_perls(); is scalar( @vers ), 16, "Correct number of releases found"; my @known_perl_versions = ( 'perl-5.28.0', 'perl-5.26.2', 'perl-5.24.4', 'perl-5.22.4', 'perl-5.20.3', 'perl-5.18.4', 'perl-5.16.3', 'perl-5.14.4', 'perl-5.13.11', 'perl-5.12.5', 'perl-5.10.1', 'perl-5.8.9', 'perl-5.6.2', 'perl5.005_04', 'perl5.004_05', 'perl5.003_07' ); for my $perl_version ( $app->available_perls() ) { ok grep( $_ eq $perl_version, @known_perl_versions ), "$perl_version found"; } sub read_cpan_html { return <<'EOF'; Perl Source - www.cpan.org

Perl Source

Perl compiles on over 100 platforms, if you want to install from a binary instead see the ports page (especially for Windows).

How to install from source

     wget http://www.cpan.org/src/perl-5.12.3.tar.gz
     tar -xzf perl-5.12.3.tar.gz
     cd perl-5.12.3
     ./Configure -des -Dprefix=$HOME/localperl
     make
     make test
     make install

Read both INSTALL and README.yoursystem in the perl-5.12.3 directory for more detailed information.

Latest releases in each branch of Perl

Major Version Type Released Download
5.13 5.13.11 Devel 2011-03-20 perl-5.13.11.tar.bz2
5.12 5.12.5 Maint 2011-01-22 perl-5.12.5.tar.gz
5.10 5.10.1 Maint 2009-08-23 perl-5.10.1.tar.gz
5.8 5.8.9 Maint 2008-12-14 perl-5.8.9.tar.gz
5.6 5.6.2 Maint 2003-11-15 perl-5.6.2.tar.gz
5.5 5.5.4 Maint 2004-02-23 perl5.005_04.tar.gz
5.4 5.4.5 Maint 1999-04-29 perl5.004_05.tar.gz
5.3 5.3.7 Maint 1996-10-10 perl5.003_07.tar.gz

Perl History

If you want to help out developing new releases of Perl visit the development site and join the perl5-porters mailing list.

Version scheme

Perl has used the following policy since the 5.6 release of Perl:

  • Maintenance branches (ready for production use) are even numbers (5.8, 5.10, 5.12 etc)
  • Sub-branches of maintenance releases (5.12.1, 5.12.2 etc) are mostly just for bug fixes
  • Development branches are odd numbers (5.9, 5.11, 5.13 etc)
  • RC (release candidates) leading up to a maintenance branch are called testing releases

Please note that branches earlier than 5.8 are no longer supported, though fixes for urgent issues, for example severe security problems, may still be issued.

Note: please avoid referring to the "symbolic" source releases like "stable" and "latest", or "maint" and "devel". They are still used here but only for backward compatibility. The symbolic names were found to cause more confusion than they are worth because they don't really work with multiple branches, especially not with multiple maintenance branches, and especially the "latest" makes absolutely no sense. The "latest" and "stable" are now just aliases for "maint", and "maint" in turn is the maintenance branch with the largest release number.

First release in each branch of Perl

Major Version Released
5.12 5.12.0 2010-04-12
5.10 5.10.0 2007-12-18
5.8 5.8.0 2002-07-18
5.6 5.6.0 2000-03-22
5.5 5.5.0 1998-07-22
5.4 5.4.0 1997-05-15
5.3 5.3.7 1996-10-10

Other files and directories (mostly for posterity)

  • 5.0/

    Source archives for all releases of perl5. You should only need to look here if you have an application which, for some reason or another, does not run with the current release of perl5. Be aware that only 5.004 and later versions of perl are maintained. If you report a genuine bug in such a version, you will probably be informed either that it is fixed in the current maintenance release, or will be fixed in a subsequent one. If you report a bug in an unmaintained version, you are likely to be advised to upgrade to a maintained version which fixes the bug, or to await a fix in a maintained version. No fix will be provided for the unmaintained version.

  • Perl 6 or Parrot are not yet in CPAN. In the meanwhile, try here or here.

  • 5.0/jperl

    Path to patch files needed to adapt particular perl releases for use with Japanese character sets.

  • ENDINGS

    Discussion of the meanings of the endings of filenames (.gz, .ZIP and so on). Read this file if you want to know how to handle a source code archive after you've downloaded it.

  • README

    This file.

  • misc/

    Third-party and other add-on source packages needed in order to build certain perl configurations. You do not need any of this stuff to build a default configuration.

  • perl-5.*.tar.gz, perl-5.*.tar.bz2, perl5_*.tar.gz

    Source code archives for several recent production releases of perl.

  • unsupported/

    This is where we hid the source for perl4, which was superseded by perl5 years ago. We would really much rather that you didn't use it. It is definitely obsolete and has security and other bugs. And, since it's unsupported, it will continue to have them.

  • 5.0/sperl-2000-08-05

    Files relevant to the security problem found in 'suidperl' in August 2000, reported in the bugtraq mailing list. The problem was found in all Perl release branches: 5.6, 5.005, and 5.004. The 5.6.1 release has a fix for this, as have the 5.8 releases. The (now obsolete) development branch 5.7 was unaffected, except for very early (pre-5.7.0) developer-only snapshots. The bug affects you only if you use an executable called 'suidperl', not if you use 'perl', and it is very likely only to affect UNIX platforms, and even more precisely, as of March 2001, the only platforms known to be affected are Linux platforms (all of them, as far as we know). The 'suidperl' is an optional component which is not installed, or even built, by default. These files will help you in the case you compile Perl yourself from the source and you want to close the security hole.

  • 5.0/CA-97.17.sperl
  • 5.0/fixsperl-0
  • 5.0/fixsuid5-0.pat

    Files relevant to the CERT Advisory CA-97.17.sperl, a security problem found in 'suidperl' back in 1997. The problem was found both in Perl 4.036 (the final) (and last) release of Perl 4 and in early versions of Perl 5 (pre-5.003). The bug affects you only if you use an executable called 'suidperl', not if you use 'perl', and it is very likely only to affect UNIX platform. The 'suidperl' is an optional component which is not installed, or even built, by default. These files will help you in the (very unlikely) case you need to use (the obsolete and unsupported) Perl 4 or the early Perl 5s, Perl releases newer than Perl 5.003 do not have this security problem.

EOF } sub read_metacpan_html { return <<'EOF'; { "releases" : [ { "authorized" : true, "version" : "5.028000", "maturity" : "released", "status" : "latest", "name" : "perl-5.28.0", "date" : "2018-06-23T02:05:28", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.28.0.tar.gz", "author" : "XSAWYERX" }, { "name" : "perl-5.28.0-RC4", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.028000", "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.28.0-RC4.tar.gz", "date" : "2018-06-19T20:45:05" }, { "date" : "2018-06-18T22:47:34", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.28.0-RC3.tar.gz", "author" : "XSAWYERX", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.28.0-RC3", "version" : "5.028000", "authorized" : true }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.28.0-RC2", "version" : "5.028000", "authorized" : true, "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.28.0-RC2.tar.gz", "date" : "2018-06-06T12:34:00" }, { "version" : "5.028000", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.28.0-RC1", "date" : "2018-05-21T13:12:00", "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.28.0-RC1.tar.gz" }, { "version" : "5.027011", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.27.11", "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.27.11.tar.gz", "date" : "2018-04-20T15:10:52" }, { "date" : "2018-04-14T11:27:18", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.26.2.tar.gz", "author" : "SHAY", "name" : "perl-5.26.2", "maturity" : "released", "status" : "cpan", "authorized" : true, "version" : "5.026002" }, { "date" : "2018-04-14T11:25:22", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.4.tar.gz", "version" : "5.024004", "authorized" : true, "name" : "perl-5.24.4", "status" : "cpan", "maturity" : "released" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.26.2-RC1", "version" : "5.026002", "authorized" : true, "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.26.2-RC1.tar.gz", "date" : "2018-03-24T19:37:40" }, { "version" : "5.024004", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.24.4-RC1", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.4-RC1.tar.gz", "author" : "SHAY", "date" : "2018-03-24T19:33:50" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.27.10", "version" : "5.027010", "authorized" : true, "date" : "2018-03-20T21:08:53", "download_url" : "https://cpan.metacpan.org/authors/id/T/TO/TODDR/perl-5.27.10.tar.gz", "author" : "TODDR" }, { "date" : "2018-02-20T20:46:45", "download_url" : "https://cpan.metacpan.org/authors/id/R/RE/RENEEB/perl-5.27.9.tar.gz", "author" : "RENEEB", "name" : "perl-5.27.9", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.027009" }, { "authorized" : true, "version" : "5.027008", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.27.8", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.27.8.tar.gz", "author" : "ABIGAIL", "date" : "2018-01-20T03:17:50" }, { "date" : "2017-12-20T22:58:25", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.27.7.tar.gz", "author" : "BINGOS", "version" : "5.027007", "authorized" : true, "name" : "perl-5.27.7", "status" : "cpan", "maturity" : "developer" }, { "download_url" : "https://cpan.metacpan.org/authors/id/E/ET/ETHER/perl-5.27.6.tar.gz", "author" : "ETHER", "date" : "2017-11-20T22:39:31", "name" : "perl-5.27.6", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.027006" }, { "name" : "perl-5.27.5", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.027005", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.27.5.tar.gz", "author" : "SHAY", "date" : "2017-10-20T22:08:15" }, { "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.26.1.tar.bz2", "author" : "SHAY", "date" : "2017-09-22T21:30:18", "authorized" : true, "version" : "5.026001", "status" : "latest", "maturity" : "released", "name" : "perl-5.26.1" }, { "date" : "2017-09-22T21:29:50", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.3.tar.gz", "authorized" : true, "version" : "5.024003", "status" : "cpan", "maturity" : "released", "name" : "perl-5.24.3" }, { "author" : "GENEHACK", "download_url" : "https://cpan.metacpan.org/authors/id/G/GE/GENEHACK/perl-5.27.4.tar.bz2", "date" : "2017-09-20T21:44:22", "version" : "5.027004", "authorized" : true, "name" : "perl-5.27.4", "status" : "cpan", "maturity" : "developer" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.26.1-RC1", "version" : "5.026001", "authorized" : true, "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.26.1-RC1.tar.bz2", "date" : "2017-09-10T15:38:22" }, { "authorized" : true, "version" : "5.024003", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.24.3-RC1", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.3-RC1.tar.bz2", "date" : "2017-09-10T15:37:08" }, { "author" : "WOLFSAGE", "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.27.3.tar.bz2", "date" : "2017-08-21T20:43:51", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.27.3", "authorized" : true, "version" : "5.027003" }, { "name" : "perl-5.27.2", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.027002", "date" : "2017-07-20T19:28:36", "author" : "ARC", "download_url" : "https://cpan.metacpan.org/authors/id/A/AR/ARC/perl-5.27.2.tar.bz2" }, { "version" : "5.024002", "authorized" : true, "name" : "perl-5.24.2", "maturity" : "released", "status" : "cpan", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.2.tar.gz", "date" : "2017-07-15T17:29:00" }, { "date" : "2017-07-15T17:26:52", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.4.tar.bz2", "author" : "SHAY", "authorized" : true, "version" : "5.022004", "maturity" : "released", "status" : "cpan", "name" : "perl-5.22.4" }, { "version" : "5.024002", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.24.2-RC1", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.2-RC1.tar.bz2", "author" : "SHAY", "date" : "2017-07-01T21:50:55" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.22.4-RC1", "authorized" : true, "version" : "5.022004", "date" : "2017-07-01T21:50:24", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.4-RC1.tar.gz" }, { "name" : "perl-5.27.1", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.027001", "download_url" : "https://cpan.metacpan.org/authors/id/E/EH/EHERMAN/perl-5.27.1.tar.bz2", "author" : "EHERMAN", "date" : "2017-06-20T06:39:54" }, { "maturity" : "developer", "status" : "backpan", "name" : "perl-5.27.0", "version" : "5.027000", "authorized" : true, "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.27.0.tar.gz", "date" : "2017-05-31T21:11:57" }, { "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.26.0.tar.bz2", "author" : "XSAWYERX", "date" : "2017-05-30T19:42:51", "authorized" : true, "version" : "5.026000", "status" : "cpan", "maturity" : "released", "name" : "perl-5.26.0" }, { "name" : "perl-5.26.0-RC2", "maturity" : "developer", "status" : "backpan", "authorized" : true, "version" : "5.026000", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.26.0-RC2.tar.gz", "author" : "XSAWYERX", "date" : "2017-05-23T23:19:34" }, { "name" : "perl-5.26.0-RC1", "status" : "backpan", "maturity" : "developer", "authorized" : true, "version" : "5.026000", "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.26.0-RC1.tar.bz2", "date" : "2017-05-11T17:07:17" }, { "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.25.12.tar.gz", "date" : "2017-04-20T19:32:05", "maturity" : "developer", "status" : "backpan", "name" : "perl-5.25.12", "version" : "5.025012", "authorized" : true }, { "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.25.11.tar.gz", "date" : "2017-03-20T20:56:49", "version" : "5.025011", "authorized" : true, "maturity" : "developer", "status" : "backpan", "name" : "perl-5.25.11" }, { "date" : "2017-02-20T21:21:01", "author" : "RENEEB", "download_url" : "https://cpan.metacpan.org/authors/id/R/RE/RENEEB/perl-5.25.10.tar.gz", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.25.10", "version" : "5.025010", "authorized" : true }, { "name" : "perl-5.25.9", "maturity" : "developer", "status" : "cpan", "version" : "5.025009", "authorized" : true, "date" : "2017-01-20T15:25:43", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.25.9.tar.gz", "author" : "ABIGAIL" }, { "authorized" : true, "version" : "5.024001", "name" : "perl-5.24.1", "status" : "cpan", "maturity" : "released", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1.tar.bz2", "date" : "2017-01-14T20:04:30" }, { "date" : "2017-01-14T20:04:05", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3.tar.gz", "maturity" : "released", "status" : "cpan", "name" : "perl-5.22.3", "version" : "5.022003", "authorized" : true }, { "date" : "2017-01-02T18:57:38", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1-RC5.tar.bz2", "authorized" : true, "version" : "5.024001", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.24.1-RC5" }, { "authorized" : true, "version" : "5.022003", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.22.3-RC5", "date" : "2017-01-02T18:54:51", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3-RC5.tar.bz2", "author" : "SHAY" }, { "authorized" : true, "version" : "5.025008", "name" : "perl-5.25.8", "status" : "backpan", "maturity" : "developer", "date" : "2016-12-20T19:14:33", "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.25.8.tar.gz" }, { "name" : "perl-5.25.7", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.025007", "date" : "2016-11-20T21:20:07", "author" : "EXODIST", "download_url" : "https://cpan.metacpan.org/authors/id/E/EX/EXODIST/perl-5.25.7.tar.bz2" }, { "date" : "2016-10-20T15:44:55", "author" : "ARC", "download_url" : "https://cpan.metacpan.org/authors/id/A/AR/ARC/perl-5.25.6.tar.bz2", "version" : "5.025006", "authorized" : true, "name" : "perl-5.25.6", "status" : "cpan", "maturity" : "developer" }, { "authorized" : true, "version" : "5.024001", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.24.1-RC4", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1-RC4.tar.bz2", "date" : "2016-10-12T21:40:57" }, { "authorized" : true, "version" : "5.022003", "name" : "perl-5.22.3-RC4", "status" : "cpan", "maturity" : "developer", "date" : "2016-10-12T21:39:57", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3-RC4.tar.bz2" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.25.5", "authorized" : true, "version" : "5.025005", "date" : "2016-09-20T17:45:06", "author" : "STEVAN", "download_url" : "https://cpan.metacpan.org/authors/id/S/ST/STEVAN/perl-5.25.5.tar.bz2" }, { "date" : "2016-08-20T20:25:19", "author" : "BINGOS", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.25.4.tar.bz2", "version" : "5.025004", "authorized" : true, "name" : "perl-5.25.4", "maturity" : "developer", "status" : "cpan" }, { "date" : "2016-08-11T23:50:29", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1-RC3.tar.bz2", "author" : "SHAY", "version" : "5.024001", "authorized" : true, "name" : "perl-5.24.1-RC3", "status" : "cpan", "maturity" : "developer" }, { "authorized" : true, "version" : "5.022003", "name" : "perl-5.22.3-RC3", "status" : "cpan", "maturity" : "developer", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3-RC3.tar.bz2", "author" : "SHAY", "date" : "2016-08-11T23:47:40" }, { "authorized" : true, "version" : "5.024001", "name" : "perl-5.24.1-RC2", "maturity" : "developer", "status" : "cpan", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1-RC2.tar.bz2", "date" : "2016-07-25T13:01:21" }, { "version" : "5.022003", "authorized" : true, "name" : "perl-5.22.3-RC2", "status" : "cpan", "maturity" : "developer", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3-RC2.tar.bz2", "date" : "2016-07-25T12:58:33" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.25.3", "version" : "5.025003", "authorized" : true, "date" : "2016-07-20T16:22:41", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.25.3.tar.bz2", "author" : "SHAY" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.24.1-RC1", "version" : "5.024001", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.24.1-RC1.tar.bz2", "author" : "SHAY", "date" : "2016-07-17T22:29:08" }, { "version" : "5.022003", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.22.3-RC1", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.3-RC1.tar.bz2", "author" : "SHAY", "date" : "2016-07-17T22:27:32" }, { "author" : "WOLFSAGE", "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.25.2.tar.bz2", "date" : "2016-06-20T21:02:44", "name" : "perl-5.25.2", "maturity" : "developer", "status" : "cpan", "version" : "5.025002", "authorized" : true }, { "author" : "XSAWYERX", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.25.1.tar.bz2", "date" : "2016-05-20T21:33:43", "name" : "perl-5.25.1", "status" : "backpan", "maturity" : "developer", "authorized" : true, "version" : "5.025001" }, { "date" : "2016-05-09T12:02:53", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.25.0.tar.bz2", "author" : "RJBS", "version" : "5.025000", "authorized" : true, "name" : "perl-5.25.0", "maturity" : "developer", "status" : "cpan" }, { "authorized" : true, "version" : "5.024000", "maturity" : "released", "status" : "cpan", "name" : "perl-5.24.0", "date" : "2016-05-09T11:35:29", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0.tar.bz2", "author" : "RJBS" }, { "name" : "perl-5.24.0-RC5", "status" : "cpan", "maturity" : "developer", "version" : "5.024000", "authorized" : true, "date" : "2016-05-04T22:27:57", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0-RC5.tar.bz2", "author" : "RJBS" }, { "version" : "5.024000", "authorized" : true, "name" : "perl-5.24.0-RC4", "maturity" : "developer", "status" : "cpan", "date" : "2016-05-02T14:41:03", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0-RC4.tar.bz2" }, { "date" : "2016-04-29T21:39:25", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.2.tar.bz2", "version" : "5.022002", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.22.2" }, { "version" : "5.024000", "authorized" : true, "name" : "perl-5.24.0-RC3", "maturity" : "developer", "status" : "cpan", "date" : "2016-04-27T01:02:55", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0-RC3.tar.bz2" }, { "authorized" : true, "version" : "5.024000", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.24.0-RC2", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0-RC2.tar.bz2", "date" : "2016-04-23T20:56:14" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.24.0-RC1", "version" : "5.024000", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.24.0-RC1.tar.bz2", "author" : "RJBS", "date" : "2016-04-14T03:27:48" }, { "authorized" : true, "version" : "5.022002", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.22.2-RC1", "date" : "2016-04-10T17:29:04", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.2-RC1.tar.bz2" }, { "date" : "2016-03-20T16:45:40", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.23.9.tar.bz2", "author" : "ABIGAIL", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.23.9", "authorized" : true, "version" : "5.023009" }, { "authorized" : true, "version" : "5.023008", "status" : "backpan", "maturity" : "developer", "name" : "perl-5.23.8", "date" : "2016-02-20T21:56:31", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.23.8.tar.bz2", "author" : "XSAWYERX" }, { "name" : "perl-5.23.7", "maturity" : "developer", "status" : "cpan", "version" : "5.023007", "authorized" : true, "date" : "2016-01-20T21:52:22", "download_url" : "https://cpan.metacpan.org/authors/id/S/ST/STEVAN/perl-5.23.7.tar.bz2", "author" : "STEVAN" }, { "date" : "2015-12-21T22:40:27", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAGOLDEN/perl-5.23.6.tar.bz2", "author" : "DAGOLDEN", "name" : "perl-5.23.6", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.023006" }, { "version" : "5.022001", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.22.1", "date" : "2015-12-13T19:48:31", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.1.tar.gz", "author" : "SHAY" }, { "version" : "5.022001", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.22.1-RC4", "date" : "2015-12-08T21:34:05", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.1-RC4.tar.bz2", "author" : "SHAY" }, { "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.1-RC3.tar.bz2", "author" : "SHAY", "date" : "2015-12-02T22:07:35", "version" : "5.022001", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.22.1-RC3" }, { "authorized" : true, "version" : "5.023005", "name" : "perl-5.23.5", "maturity" : "developer", "status" : "cpan", "author" : "ABIGAIL", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.23.5.tar.bz2", "date" : "2015-11-20T17:09:38" }, { "date" : "2015-11-15T15:15:03", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.1-RC2.tar.bz2", "author" : "SHAY", "authorized" : true, "version" : "5.022001", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.22.1-RC2" }, { "date" : "2015-10-31T18:42:58", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.22.1-RC1.tar.bz2", "author" : "SHAY", "authorized" : true, "version" : "5.022001", "name" : "perl-5.22.1-RC1", "status" : "cpan", "maturity" : "developer" }, { "date" : "2015-10-20T22:17:48", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.23.4.tar.bz2", "author" : "SHAY", "authorized" : true, "version" : "5.023004", "name" : "perl-5.23.4", "maturity" : "developer", "status" : "cpan" }, { "version" : "5.023003", "authorized" : true, "name" : "perl-5.23.3", "maturity" : "developer", "status" : "cpan", "date" : "2015-09-21T02:47:16", "author" : "PCM", "download_url" : "https://cpan.metacpan.org/authors/id/P/PC/PCM/perl-5.23.3.tar.bz2" }, { "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.3.tar.bz2", "author" : "SHAY", "date" : "2015-09-12T19:09:14", "version" : "5.020003", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.20.3" }, { "date" : "2015-08-29T22:02:43", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.3-RC2.tar.bz2", "authorized" : true, "version" : "5.020003", "name" : "perl-5.20.3-RC2", "status" : "cpan", "maturity" : "developer" }, { "version" : "5.020003", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.20.3-RC1", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.3-RC1.tar.bz2", "date" : "2015-08-22T22:12:34" }, { "date" : "2015-08-20T15:36:45", "author" : "WOLFSAGE", "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.23.2.tar.bz2", "name" : "perl-5.23.2", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.023002" }, { "authorized" : true, "version" : "5.023001", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.23.1", "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.23.1.tar.bz2", "author" : "WOLFSAGE", "date" : "2015-07-20T19:26:31" }, { "version" : "5.023000", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.23.0", "date" : "2015-06-20T20:22:32", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.23.0.tar.bz2" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.22.0.tar.bz2", "date" : "2015-06-01T17:51:59", "version" : "5.022000", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.22.0" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.22.0-RC2.tar.bz2", "date" : "2015-05-21T23:03:22", "name" : "perl-5.22.0-RC2", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.022000" }, { "date" : "2015-05-19T14:12:19", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.22.0-RC1.tar.bz2", "author" : "RJBS", "version" : "5.022000", "authorized" : true, "name" : "perl-5.22.0-RC1", "maturity" : "developer", "status" : "cpan" }, { "authorized" : true, "version" : "5.021011", "name" : "perl-5.21.11", "maturity" : "developer", "status" : "cpan", "date" : "2015-04-20T21:28:37", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.21.11.tar.bz2", "author" : "SHAY" }, { "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.21.10.tar.bz2", "author" : "SHAY", "date" : "2015-03-20T18:30:20", "version" : "5.021010", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.21.10" }, { "date" : "2015-02-21T05:27:09", "download_url" : "https://cpan.metacpan.org/authors/id/X/XS/XSAWYERX/perl-5.21.9.tar.bz2", "author" : "XSAWYERX", "name" : "perl-5.21.9", "maturity" : "developer", "status" : "backpan", "authorized" : true, "version" : "5.021009" }, { "authorized" : true, "version" : "5.020002", "name" : "perl-5.20.2", "status" : "cpan", "maturity" : "released", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.2.tar.bz2", "author" : "SHAY", "date" : "2015-02-14T18:26:43" }, { "date" : "2015-02-01T03:07:56", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.2-RC1.tar.bz2", "version" : "5.020002", "authorized" : true, "name" : "perl-5.20.2-RC1", "status" : "cpan", "maturity" : "developer" }, { "date" : "2015-01-20T20:20:05", "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.21.8.tar.bz2", "author" : "WOLFSAGE", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.21.8", "version" : "5.021008", "authorized" : true }, { "author" : "CORION", "download_url" : "https://cpan.metacpan.org/authors/id/C/CO/CORION/perl-5.21.7.tar.bz2", "date" : "2014-12-20T17:34:57", "name" : "perl-5.21.7", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.021007" }, { "date" : "2014-11-20T23:39:06", "author" : "BINGOS", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.21.6.tar.bz2", "authorized" : true, "version" : "5.021006", "name" : "perl-5.21.6", "maturity" : "developer", "status" : "cpan" }, { "version" : "5.021005", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.21.5", "date" : "2014-10-20T16:54:20", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.21.5.tar.bz2", "author" : "ABIGAIL" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.4.tar.bz2", "author" : "RJBS", "date" : "2014-10-02T00:48:31", "status" : "cpan", "maturity" : "released", "name" : "perl-5.18.4", "version" : "5.018004", "authorized" : true }, { "version" : "5.018003", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.18.3", "date" : "2014-10-01T13:22:50", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.3.tar.bz2", "author" : "RJBS" }, { "date" : "2014-09-27T12:54:08", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.3-RC2.tar.bz2", "version" : "5.018003", "authorized" : true, "name" : "perl-5.18.3-RC2", "maturity" : "developer", "status" : "cpan" }, { "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.21.4.tar.bz2", "date" : "2014-09-20T13:33:14", "name" : "perl-5.21.4", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.021004" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.3-RC1.tar.bz2", "author" : "RJBS", "date" : "2014-09-17T20:29:53", "name" : "perl-5.18.3-RC1", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.018003" }, { "authorized" : true, "version" : "5.020001", "maturity" : "released", "status" : "cpan", "name" : "perl-5.20.1", "date" : "2014-09-14T13:11:14", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.1.tar.bz2" }, { "date" : "2014-09-07T17:01:11", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.1-RC2.tar.bz2", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.20.1-RC2", "version" : "5.020001", "authorized" : true }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.20.1-RC1", "authorized" : true, "version" : "5.020001", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.20.1-RC1.tar.bz2", "date" : "2014-08-25T18:10:32" }, { "version" : "5.021003", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.21.3", "author" : "PCM", "download_url" : "https://cpan.metacpan.org/authors/id/P/PC/PCM/perl-5.21.3.tar.bz2", "date" : "2014-08-21T02:26:13" }, { "author" : "ABIGAIL", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.21.2.tar.bz2", "date" : "2014-07-20T13:48:02", "version" : "5.021002", "authorized" : true, "name" : "perl-5.21.2", "status" : "cpan", "maturity" : "developer" }, { "download_url" : "https://cpan.metacpan.org/authors/id/W/WO/WOLFSAGE/perl-5.21.1.tar.bz2", "author" : "WOLFSAGE", "date" : "2014-06-20T15:31:10", "version" : "5.021001", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.21.1" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.21.0", "authorized" : true, "version" : "5.021000", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.21.0.tar.bz2", "author" : "RJBS", "date" : "2014-05-27T14:32:18" }, { "version" : "5.020000", "authorized" : true, "name" : "perl-5.20.0", "maturity" : "released", "status" : "cpan", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.20.0.tar.bz2", "author" : "RJBS", "date" : "2014-05-27T01:35:13" }, { "name" : "perl-5.20.0-RC1", "maturity" : "developer", "status" : "cpan", "version" : "5.020000", "authorized" : true, "date" : "2014-05-17T00:16:49", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.20.0-RC1.tar.bz2" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.19.11", "version" : "5.019011", "authorized" : true, "date" : "2014-04-20T15:47:12", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.19.11.tar.bz2", "author" : "SHAY" }, { "version" : "5.019010", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.19.10", "date" : "2014-03-20T20:40:26", "author" : "ARC", "download_url" : "https://cpan.metacpan.org/authors/id/A/AR/ARC/perl-5.19.10.tar.bz2" }, { "version" : "5.019009", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.19.9", "download_url" : "https://cpan.metacpan.org/authors/id/T/TO/TONYC/perl-5.19.9.tar.bz2", "author" : "TONYC", "date" : "2014-02-20T04:24:45" }, { "date" : "2014-01-20T21:59:04", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.19.8.tar.bz2", "author" : "RJBS", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.8", "version" : "5.019008", "authorized" : true }, { "maturity" : "released", "status" : "cpan", "name" : "perl-5.18.2", "version" : "5.018002", "authorized" : true, "date" : "2014-01-07T01:52:57", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.2.tar.bz2" }, { "date" : "2013-12-22T03:30:43", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.2-RC4.tar.bz2", "author" : "RJBS", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.18.2-RC4", "authorized" : true, "version" : "5.018002" }, { "author" : "ABIGAIL", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.19.7.tar.bz2", "date" : "2013-12-20T20:55:37", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.7", "authorized" : true, "version" : "5.019007" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.2-RC3.tar.bz2", "author" : "RJBS", "date" : "2013-12-19T21:27:42", "name" : "perl-5.18.2-RC3", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.018002" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.2-RC2.tar.bz2", "date" : "2013-12-07T13:55:43", "version" : "5.018002", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.18.2-RC2" }, { "authorized" : true, "version" : "5.018002", "name" : "perl-5.18.2-RC1", "status" : "cpan", "maturity" : "developer", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.2-RC1.tar.bz2", "date" : "2013-12-02T22:36:49" }, { "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.19.6.tar.bz2", "author" : "BINGOS", "date" : "2013-11-20T20:37:20", "version" : "5.019006", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.19.6" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.5", "version" : "5.019005", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.19.5.tar.bz2", "author" : "SHAY", "date" : "2013-10-20T13:25:55" }, { "name" : "perl-5.19.4", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.019004", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.19.4.tar.bz2", "date" : "2013-09-20T15:58:20" }, { "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.19.3.tar.bz2", "date" : "2013-08-20T16:09:42", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.3", "authorized" : true, "version" : "5.019003" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.1.tar.bz2", "date" : "2013-08-12T14:31:08", "maturity" : "released", "status" : "cpan", "name" : "perl-5.18.1", "authorized" : true, "version" : "5.018001" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.18.1-RC3", "authorized" : true, "version" : "5.018001", "date" : "2013-08-09T02:28:00", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.1-RC3.tar.bz2" }, { "authorized" : true, "version" : "5.018001", "name" : "perl-5.18.1-RC2", "status" : "cpan", "maturity" : "developer", "date" : "2013-08-04T12:34:33", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.1-RC2.tar.bz2" }, { "date" : "2013-08-02T03:09:02", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.1-RC1.tar.bz2", "author" : "RJBS", "version" : "5.018001", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.18.1-RC1" }, { "download_url" : "https://cpan.metacpan.org/authors/id/A/AR/ARISTOTLE/perl-5.19.2.tar.bz2", "author" : "ARISTOTLE", "date" : "2013-07-22T05:59:35", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.19.2", "version" : "5.019002", "authorized" : true }, { "author" : "DAGOLDEN", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAGOLDEN/perl-5.19.1.tar.bz2", "date" : "2013-06-21T01:24:18", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.1", "authorized" : true, "version" : "5.019001" }, { "authorized" : true, "version" : "5.019000", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.19.0", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.19.0.tar.bz2", "date" : "2013-05-20T13:12:38" }, { "date" : "2013-05-18T13:33:49", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.0.tar.bz2", "author" : "RJBS", "version" : "5.018000", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.18.0" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.0-RC4.tar.bz2", "date" : "2013-05-16T02:53:44", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.18.0-RC4", "version" : "5.018000", "authorized" : true }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.0-RC3.tar.bz2", "author" : "RJBS", "date" : "2013-05-14T01:32:05", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.18.0-RC3", "authorized" : true, "version" : "5.018000" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.0-RC2.tar.bz2", "author" : "RJBS", "date" : "2013-05-12T23:14:51", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.18.0-RC2", "authorized" : true, "version" : "5.018000" }, { "date" : "2013-05-11T12:29:53", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.18.0-RC1.tar.bz2", "name" : "perl-5.18.0-RC1", "status" : "cpan", "maturity" : "developer", "version" : "5.018000", "authorized" : true }, { "version" : "5.017011", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.17.11", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.17.11.tar.bz2", "date" : "2013-04-21T00:52:16" }, { "version" : "5.017010", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.17.10", "author" : "CORION", "download_url" : "https://cpan.metacpan.org/authors/id/C/CO/CORION/perl-5.17.10.tar.bz2", "date" : "2013-03-21T23:11:03" }, { "date" : "2013-03-11T21:08:33", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.3.tar.bz2", "author" : "RJBS", "version" : "5.016003", "authorized" : true, "maturity" : "released", "status" : "cpan", "name" : "perl-5.16.3" }, { "author" : "DAPM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.14.4.tar.bz2", "date" : "2013-03-10T23:47:40", "name" : "perl-5.14.4", "maturity" : "released", "status" : "cpan", "version" : "5.014004", "authorized" : true }, { "author" : "DAPM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.14.4-RC2.tar.bz2", "date" : "2013-03-07T19:52:52", "authorized" : true, "version" : "5.014004", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.14.4-RC2" }, { "version" : "5.016003", "authorized" : true, "name" : "perl-5.16.3-RC1", "status" : "cpan", "maturity" : "developer", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.3-RC1.tar.bz2", "date" : "2013-03-07T16:03:14" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.14.4-RC1", "version" : "5.014004", "authorized" : true, "date" : "2013-03-05T17:03:49", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.14.4-RC1.tar.bz2", "author" : "DAPM" }, { "date" : "2013-02-20T22:21:02", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.17.9.tar.bz2", "author" : "BINGOS", "name" : "perl-5.17.9", "status" : "cpan", "maturity" : "developer", "version" : "5.017009", "authorized" : true }, { "date" : "2013-01-20T18:48:45", "download_url" : "https://cpan.metacpan.org/authors/id/A/AR/ARC/perl-5.17.8.tar.bz2", "author" : "ARC", "name" : "perl-5.17.8", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.017008" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.17.7", "version" : "5.017007", "authorized" : true, "date" : "2012-12-18T21:50:28", "download_url" : "https://cpan.metacpan.org/authors/id/D/DR/DROLSKY/perl-5.17.7.tar.bz2", "author" : "DROLSKY" }, { "version" : "5.017006", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.17.6", "date" : "2012-11-21T00:08:12", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.17.6.tar.bz2", "author" : "RJBS" }, { "maturity" : "released", "status" : "cpan", "name" : "perl-5.12.5", "version" : "5.012005", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.12.5.tar.bz2", "author" : "DOM", "date" : "2012-11-10T14:02:17" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.12.5-RC2", "version" : "5.012005", "authorized" : true, "author" : "DOM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.12.5-RC2.tar.bz2", "date" : "2012-11-08T21:12:17" }, { "name" : "perl-5.12.5-RC1", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.012005", "author" : "DOM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.12.5-RC1.tar.bz2", "date" : "2012-11-03T17:27:59" }, { "name" : "perl-5.16.2", "status" : "cpan", "maturity" : "released", "authorized" : true, "version" : "5.016002", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.2.tar.bz2", "date" : "2012-11-01T13:44:07" }, { "authorized" : true, "version" : "5.016002", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.16.2-RC1", "date" : "2012-10-27T01:23:09", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.2-RC1.tar.bz2" }, { "version" : "5.017005", "authorized" : true, "name" : "perl-5.17.5", "status" : "cpan", "maturity" : "developer", "author" : "FLORA", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.17.5.tar.bz2", "date" : "2012-10-20T16:31:11" }, { "maturity" : "released", "status" : "cpan", "name" : "perl-5.14.3", "version" : "5.014003", "authorized" : true, "date" : "2012-10-12T20:24:43", "author" : "DOM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.14.3.tar.bz2" }, { "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.14.3-RC2.tar.bz2", "author" : "DOM", "date" : "2012-10-10T19:46:29", "version" : "5.014003", "authorized" : true, "name" : "perl-5.14.3-RC2", "status" : "cpan", "maturity" : "developer" }, { "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOM/perl-5.14.3-RC1.tar.bz2", "author" : "DOM", "date" : "2012-09-26T22:15:57", "authorized" : true, "version" : "5.014003", "name" : "perl-5.14.3-RC1", "maturity" : "developer", "status" : "cpan" }, { "date" : "2012-09-20T00:40:48", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.17.4.tar.bz2", "author" : "FLORA", "authorized" : true, "version" : "5.017004", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.17.4" }, { "name" : "perl-5.17.3", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.017003", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.17.3.tar.bz2", "date" : "2012-08-20T14:12:28" }, { "date" : "2012-08-08T22:30:11", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.1.tar.bz2", "author" : "RJBS", "authorized" : true, "version" : "5.016001", "name" : "perl-5.16.1", "maturity" : "released", "status" : "cpan" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.1-RC1.tar.bz2", "author" : "RJBS", "date" : "2012-08-03T18:59:23", "version" : "5.016001", "authorized" : true, "name" : "perl-5.16.1-RC1", "status" : "cpan", "maturity" : "developer" }, { "name" : "perl-5.17.2", "status" : "cpan", "maturity" : "developer", "version" : "5.017002", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/T/TO/TONYC/perl-5.17.2.tar.bz2", "author" : "TONYC", "date" : "2012-07-20T14:27:59" }, { "version" : "5.017001", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.17.1", "date" : "2012-06-20T17:38:46", "download_url" : "https://cpan.metacpan.org/authors/id/D/DO/DOY/perl-5.17.1.tar.bz2", "author" : "DOY" }, { "author" : "ZEFRAM", "download_url" : "https://cpan.metacpan.org/authors/id/Z/ZE/ZEFRAM/perl-5.17.0.tar.bz2", "date" : "2012-05-26T16:24:02", "name" : "perl-5.17.0", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.017000" }, { "date" : "2012-05-20T22:51:12", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.0.tar.bz2", "author" : "RJBS", "version" : "5.016000", "authorized" : true, "maturity" : "released", "status" : "cpan", "name" : "perl-5.16.0" }, { "version" : "5.016000", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.16.0-RC2", "date" : "2012-05-16T03:22:59", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.0-RC2.tar.bz2" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.0-RC1.tar.bz2", "date" : "2012-05-15T02:51:48", "authorized" : true, "version" : "5.016000", "name" : "perl-5.16.0-RC1", "maturity" : "developer", "status" : "cpan" }, { "date" : "2012-05-11T03:41:02", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.16.0-RC0.tar.bz2", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.16.0-RC0", "version" : "5.016000", "authorized" : true }, { "date" : "2012-03-20T19:01:29", "download_url" : "https://cpan.metacpan.org/authors/id/A/AB/ABIGAIL/perl-5.15.9.tar.bz2", "author" : "ABIGAIL", "name" : "perl-5.15.9", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.015009" }, { "download_url" : "https://cpan.metacpan.org/authors/id/C/CO/CORION/perl-5.15.8.tar.bz2", "author" : "CORION", "date" : "2012-02-20T22:38:13", "authorized" : true, "version" : "5.015008", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.15.8" }, { "authorized" : true, "version" : "5.015007", "name" : "perl-5.15.7", "status" : "cpan", "maturity" : "developer", "date" : "2012-01-20T20:08:28", "author" : "BINGOS", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.15.7.tar.bz2" }, { "download_url" : "https://cpan.metacpan.org/authors/id/D/DR/DROLSKY/perl-5.15.6.tar.bz2", "author" : "DROLSKY", "date" : "2011-12-20T17:55:58", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.15.6", "version" : "5.015006", "authorized" : true }, { "name" : "perl-5.15.5", "maturity" : "developer", "status" : "cpan", "version" : "5.015005", "authorized" : true, "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.15.5.tar.bz2", "date" : "2011-11-20T20:40:34" }, { "date" : "2011-10-20T21:17:45", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.15.4.tar.bz2", "author" : "FLORA", "name" : "perl-5.15.4", "maturity" : "developer", "status" : "cpan", "version" : "5.015004", "authorized" : true }, { "version" : "5.014002", "authorized" : true, "maturity" : "released", "status" : "cpan", "name" : "perl-5.14.2", "author" : "FLORA", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.14.2.tar.bz2", "date" : "2011-09-26T14:56:49" }, { "author" : "STEVAN", "download_url" : "https://cpan.metacpan.org/authors/id/S/ST/STEVAN/perl-5.15.3.tar.bz2", "date" : "2011-09-21T03:05:05", "authorized" : true, "version" : "5.015003", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.15.3" }, { "date" : "2011-09-19T11:25:31", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.14.2-RC1.tar.bz2", "author" : "FLORA", "name" : "perl-5.14.2-RC1", "maturity" : "developer", "status" : "cpan", "version" : "5.014002", "authorized" : true }, { "date" : "2011-08-21T00:05:23", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.15.2.tar.bz2", "author" : "RJBS", "version" : "5.015002", "authorized" : true, "name" : "perl-5.15.2", "status" : "cpan", "maturity" : "developer" }, { "version" : "5.015001", "authorized" : true, "name" : "perl-5.15.1", "status" : "cpan", "maturity" : "developer", "date" : "2011-07-20T21:15:08", "author" : "ZEFRAM", "download_url" : "https://cpan.metacpan.org/authors/id/Z/ZE/ZEFRAM/perl-5.15.1.tar.bz2" }, { "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAGOLDEN/perl-5.15.0.tar.bz2", "author" : "DAGOLDEN", "date" : "2011-06-20T23:19:05", "authorized" : true, "version" : "5.015000", "name" : "perl-5.15.0", "status" : "cpan", "maturity" : "developer" }, { "name" : "perl-5.12.4", "maturity" : "released", "status" : "cpan", "version" : "5.012004", "authorized" : true, "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl-5.12.4.tar.bz2", "date" : "2011-06-20T10:41:26" }, { "version" : "5.014001", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.14.1", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.1.tar.bz2", "date" : "2011-06-17T02:42:01" }, { "version" : "5.012004", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.12.4-RC2", "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl-5.12.4-RC2.tar.bz2", "date" : "2011-06-15T17:00:36" }, { "version" : "5.014001", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.14.1-RC1", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.1-RC1.tar.bz2", "date" : "2011-06-09T23:48:04" }, { "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl-5.12.4-RC1.tar.bz2", "date" : "2011-06-08T13:19:36", "authorized" : true, "version" : "5.012004", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.12.4-RC1" }, { "status" : "cpan", "maturity" : "released", "name" : "perl-5.14.0", "version" : "5.014000", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.0.tar.bz2", "author" : "JESSE", "date" : "2011-05-14T20:34:05" }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.0-RC3.tar.bz2", "author" : "JESSE", "date" : "2011-05-11T15:49:42", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.14.0-RC3", "version" : "5.014000", "authorized" : true }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.0-RC2.tar.bz2", "author" : "JESSE", "date" : "2011-05-04T16:42:27", "name" : "perl-5.14.0-RC2", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.014000" }, { "name" : "perl-5.14.0-RC1", "maturity" : "developer", "status" : "cpan", "version" : "5.014000", "authorized" : true, "date" : "2011-04-20T11:53:32", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.14.0-RC1.tar.bz2" }, { "authorized" : true, "version" : "5.013011", "name" : "perl-5.13.11", "maturity" : "developer", "status" : "cpan", "date" : "2011-03-20T19:49:16", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.13.11.tar.bz2", "author" : "FLORA" }, { "name" : "perl-5.13.10", "status" : "cpan", "maturity" : "developer", "version" : "5.013010", "authorized" : true, "download_url" : "https://cpan.metacpan.org/authors/id/A/AV/AVAR/perl-5.13.10.tar.bz2", "author" : "AVAR", "date" : "2011-02-20T19:18:02" }, { "maturity" : "released", "status" : "cpan", "name" : "perl-5.12.3", "authorized" : true, "version" : "5.012003", "date" : "2011-01-22T03:35:35", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.12.3.tar.bz2", "author" : "RJBS" }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.13.9.tar.bz2", "author" : "JESSE", "date" : "2011-01-21T01:42:07", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.13.9", "authorized" : true, "version" : "5.013009" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.12.3-RC3", "authorized" : true, "version" : "5.012003", "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.12.3-RC3.tar.bz2", "date" : "2011-01-18T02:13:17" }, { "name" : "perl-5.12.3-RC2", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.012003", "date" : "2011-01-15T04:05:30", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.12.3-RC2.tar.bz2", "author" : "RJBS" }, { "date" : "2011-01-10T02:12:53", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.12.3-RC1.tar.bz2", "author" : "RJBS", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.12.3-RC1", "version" : "5.012003", "authorized" : true }, { "date" : "2010-12-19T23:06:25", "download_url" : "https://cpan.metacpan.org/authors/id/Z/ZE/ZEFRAM/perl-5.13.8.tar.bz2", "author" : "ZEFRAM", "name" : "perl-5.13.8", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.013008" }, { "authorized" : true, "version" : "5.013007", "name" : "perl-5.13.7", "maturity" : "developer", "status" : "cpan", "date" : "2010-11-21T01:14:06", "download_url" : "https://cpan.metacpan.org/authors/id/B/BI/BINGOS/perl-5.13.7.tar.bz2", "author" : "BINGOS" }, { "authorized" : true, "version" : "5.013006", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.13.6", "date" : "2010-10-21T01:41:01", "download_url" : "https://cpan.metacpan.org/authors/id/M/MI/MIYAGAWA/perl-5.13.6.tar.bz2", "author" : "MIYAGAWA" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.13.5", "authorized" : true, "version" : "5.013005", "date" : "2010-09-19T21:22:47", "author" : "SHAY", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.13.5.tar.bz2" }, { "version" : "5.012002", "authorized" : true, "maturity" : "released", "status" : "cpan", "name" : "perl-5.12.2", "date" : "2010-09-07T01:41:31", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.2.tar.bz2", "author" : "JESSE" }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.2-RC1.tar.bz2", "author" : "JESSE", "date" : "2010-08-31T16:48:01", "authorized" : true, "version" : "5.012002", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.12.2-RC1" }, { "author" : "FLORA", "download_url" : "https://cpan.metacpan.org/authors/id/F/FL/FLORA/perl-5.13.4.tar.bz2", "date" : "2010-08-20T15:39:07", "version" : "5.013004", "authorized" : true, "name" : "perl-5.13.4", "status" : "cpan", "maturity" : "developer" }, { "authorized" : true, "version" : "5.013003", "name" : "perl-5.13.3", "status" : "cpan", "maturity" : "developer", "date" : "2010-07-20T10:23:23", "author" : "DAGOLDEN", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAGOLDEN/perl-5.13.3.tar.bz2" }, { "date" : "2010-06-22T21:39:26", "author" : "MSTROUT", "download_url" : "https://cpan.metacpan.org/authors/id/M/MS/MSTROUT/perl-5.13.2.tar.bz2", "authorized" : true, "version" : "5.013002", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.13.2" }, { "author" : "RJBS", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.13.1.tar.bz2", "date" : "2010-05-20T14:03:45", "version" : "5.013001", "authorized" : true, "name" : "perl-5.13.1", "maturity" : "developer", "status" : "cpan" }, { "name" : "perl-5.12.1", "status" : "cpan", "maturity" : "released", "authorized" : true, "version" : "5.012001", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.1.tar.bz2", "date" : "2010-05-16T22:40:16" }, { "date" : "2010-05-13T22:31:41", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.1-RC2.tar.bz2", "name" : "perl-5.12.1-RC2", "status" : "cpan", "maturity" : "developer", "version" : "5.012001", "authorized" : true }, { "authorized" : true, "version" : "5.012001", "name" : "perl-5.12.1-RC1", "status" : "cpan", "maturity" : "developer", "date" : "2010-05-10T02:43:48", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.1-RC1.tar.bz2" }, { "name" : "perl-5.13.0", "status" : "cpan", "maturity" : "developer", "version" : "5.013000", "authorized" : true, "date" : "2010-04-20T20:06:02", "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl-5.13.0.tar.bz2" }, { "version" : "5.012000", "authorized" : true, "status" : "cpan", "maturity" : "released", "name" : "perl-5.12.0", "date" : "2010-04-12T22:38:37", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0.tar.bz2", "author" : "JESSE" }, { "date" : "2010-04-10T03:46:04", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC5.tar.bz2", "author" : "JESSE", "name" : "perl-5.12.0-RC5", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.012000" }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC4.tar.bz2", "author" : "JESSE", "date" : "2010-04-07T05:39:46", "version" : "5.012000", "authorized" : true, "name" : "perl-5.12.0-RC4", "status" : "cpan", "maturity" : "developer" }, { "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC3.tar.bz2", "author" : "JESSE", "date" : "2010-04-03T02:40:48", "version" : "5.012000", "authorized" : true, "name" : "perl-5.12.0-RC3", "status" : "cpan", "maturity" : "developer" }, { "authorized" : true, "version" : "5.012000", "name" : "perl-5.12.0-RC2", "maturity" : "developer", "status" : "cpan", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC2.tar.bz2", "author" : "JESSE", "date" : "2010-04-01T02:38:12" }, { "date" : "2010-03-29T18:29:49", "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC1.tar.bz2", "name" : "perl-5.12.0-RC1", "status" : "cpan", "maturity" : "developer", "authorized" : true, "version" : "5.012000" }, { "author" : "JESSE", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.12.0-RC0.tar.gz", "date" : "2010-03-21T20:41:11", "status" : "backpan", "maturity" : "developer", "name" : "perl-5.12.0-RC0", "authorized" : true, "version" : "5.012000" }, { "date" : "2010-02-21T00:45:26", "download_url" : "https://cpan.metacpan.org/authors/id/S/SH/SHAY/perl-5.11.5.tar.bz2", "author" : "SHAY", "authorized" : true, "version" : "5.011005", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.11.5" }, { "date" : "2010-01-20T16:48:28", "download_url" : "https://cpan.metacpan.org/authors/id/R/RJ/RJBS/perl-5.11.4.tar.bz2", "author" : "RJBS", "authorized" : true, "version" : "5.011004", "name" : "perl-5.11.4", "status" : "cpan", "maturity" : "developer" }, { "date" : "2009-12-21T04:49:14", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.11.3.tar.bz2", "author" : "JESSE", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.11.3", "version" : "5.011003", "authorized" : true }, { "date" : "2009-11-20T07:20:52", "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl-5.11.2.tar.bz2", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.11.2", "authorized" : true, "version" : "5.011002" }, { "date" : "2009-10-20T17:51:38", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.11.1.tar.bz2", "author" : "JESSE", "authorized" : true, "version" : "5.011001", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.11.1" }, { "date" : "2009-10-02T20:51:46", "download_url" : "https://cpan.metacpan.org/authors/id/J/JE/JESSE/perl-5.11.0.tar.bz2", "author" : "JESSE", "version" : "5.011000", "authorized" : true, "name" : "perl-5.11.0", "status" : "cpan", "maturity" : "developer" }, { "version" : "5.010001", "authorized" : true, "name" : "perl-5.10.1", "maturity" : "released", "status" : "cpan", "date" : "2009-08-23T14:21:38", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.10.1.tar.bz2", "author" : "DAPM" }, { "author" : "DAPM", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.10.1-RC2.tar.bz2", "date" : "2009-08-18T23:45:03", "authorized" : true, "version" : "5.010001", "name" : "perl-5.10.1-RC2", "maturity" : "developer", "status" : "cpan" }, { "date" : "2009-08-06T16:11:03", "download_url" : "https://cpan.metacpan.org/authors/id/D/DA/DAPM/perl-5.10.1-RC1.tar.bz2", "author" : "DAPM", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.10.1-RC1", "authorized" : true, "version" : "5.010001" }, { "date" : "2008-12-14T23:08:28", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.9.tar.bz2", "author" : "NWCLARK", "authorized" : true, "version" : "5.008009", "name" : "perl-5.8.9", "status" : "cpan", "maturity" : "released" }, { "name" : "perl-5.8.9-RC2", "status" : "cpan", "maturity" : "developer", "version" : "5.008009", "authorized" : true, "date" : "2008-12-06T22:50:35", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.9-RC2.tar.bz2" }, { "version" : "5.008009", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.8.9-RC1", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.9-RC1.tar.bz2", "date" : "2008-11-10T23:14:59" }, { "name" : "perl-5.10.0", "maturity" : "released", "status" : "cpan", "version" : "5.010000", "authorized" : true, "date" : "2007-12-18T17:41:41", "author" : "RGARCIA", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.10.0.tar.gz" }, { "version" : "5.010000", "authorized" : true, "name" : "perl-5.10.0-RC2", "maturity" : "developer", "status" : "backpan", "date" : "2007-11-25T18:22:18", "author" : "RGARCIA", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.10.0-RC2.tar.gz" }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.10.0-RC1.tar.gz", "author" : "RGARCIA", "date" : "2007-11-17T15:31:20", "maturity" : "developer", "status" : "backpan", "name" : "perl-5.10.0-RC1", "version" : "5.009005", "authorized" : true }, { "date" : "2007-07-07T16:13:57", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.9.5.tar.gz", "author" : "RGARCIA", "authorized" : true, "version" : "5.009005", "name" : "perl-5.9.5", "maturity" : "developer", "status" : "cpan" }, { "name" : "perl-0.0017", "maturity" : "developer", "status" : "backpan", "authorized" : true, "version" : "0.0017", "date" : "2007-05-01T10:37:34", "download_url" : "https://cpan.metacpan.org/authors/id/H/HO/HOOO/perl-0.0017.tar.gz", "author" : "HOOO" }, { "authorized" : true, "version" : "5.009004", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.9.4", "author" : "RGARCIA", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.9.4.tar.gz", "date" : "2006-08-15T13:48:30" }, { "date" : "2006-02-01T00:00:59", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.8.tar.bz2", "authorized" : true, "version" : "5.008008", "status" : "cpan", "maturity" : "released", "name" : "perl-5.8.8" }, { "maturity" : "developer", "status" : "cpan", "name" : "perl-5.9.3", "version" : "5.009003", "authorized" : true, "date" : "2006-01-28T11:11:38", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.9.3.tar.gz", "author" : "RGARCIA" }, { "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.8-RC1.tar.bz2", "date" : "2006-01-20T10:09:18", "authorized" : true, "version" : "5.008008", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.8.8-RC1" }, { "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.7.tar.bz2", "date" : "2005-05-30T22:19:23", "name" : "perl-5.8.7", "maturity" : "released", "status" : "cpan", "authorized" : true, "version" : "5.008007" }, { "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.7-RC1.tar.bz2", "author" : "NWCLARK", "date" : "2005-05-18T16:35:37", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.8.7-RC1", "version" : "5.008007", "authorized" : true }, { "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.9.2.tar.gz", "author" : "RGARCIA", "date" : "2005-04-01T09:53:24", "name" : "perl-5.9.2", "maturity" : "developer", "status" : "cpan", "authorized" : true, "version" : "5.009002" }, { "version" : "5.008006", "authorized" : true, "maturity" : "released", "status" : "cpan", "name" : "perl-5.8.6", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.6.tar.bz2", "author" : "NWCLARK", "date" : "2004-11-27T23:56:17" }, { "date" : "2004-11-11T19:56:33", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.6-RC1.tar.bz2", "status" : "cpan", "maturity" : "developer", "name" : "perl-5.8.6-RC1", "version" : "5.008006", "authorized" : true }, { "name" : "perl-5.8.5", "maturity" : "released", "status" : "cpan", "authorized" : true, "version" : "5.008005", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.5.tar.bz2", "author" : "NWCLARK", "date" : "2004-07-19T21:56:20" }, { "authorized" : true, "version" : "5.008005", "maturity" : "developer", "status" : "cpan", "name" : "perl-5.8.5-RC2", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.5-RC2.tar.bz2", "date" : "2004-07-08T21:55:05" }, { "authorized" : true, "version" : "5.008005", "name" : "perl-5.8.5-RC1", "status" : "cpan", "maturity" : "developer", "date" : "2004-07-06T21:41:21", "author" : "NWCLARK", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.5-RC1.tar.bz2" }, { "authorized" : true, "version" : "5.008003", "maturity" : "released", "status" : "cpan", "name" : "perl-5.8.4", "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.4.tar.bz2", "author" : "NWCLARK", "date" : "2004-04-21T23:03:10" }, { "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.4-RC2.tar.bz2", "author" : "NWCLARK", "date" : "2004-04-15T22:59:51", "version" : "5.008003", "authorized" : true, "status" : "cpan", "maturity" : "developer", "name" : "perl-5.8.4-RC2" }, { "download_url" : "https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/perl-5.8.4-RC1.tar.bz2", "author" : "NWCLARK", "date" : "2004-04-05T21:27:48", "version" : "5.008003", "authorized" : true, "maturity" : "developer", "status" : "cpan", "name" : "perl-5.8.4-RC1" }, { "status" : "cpan", "maturity" : "developer", "name" : "perl-5.9.1", "version" : "5.009001", "authorized" : true, "author" : "RGARCIA", "download_url" : "https://cpan.metacpan.org/authors/id/R/RG/RGARCIA/perl-5.9.1.tar.gz", "date" : "2004-03-16T19:35:25" }, { "date" : "2004-02-23T14:02:10", "author" : "LBROCARD", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl5.005_04.tar.gz", "status" : "cpan", "maturity" : "released", "name" : "perl5.005_04", "authorized" : true, "version" : "5.005" }, { "name" : "perl5.005_04-RC2", "maturity" : "developer", "status" : "backpan", "authorized" : true, "version" : "5.005", "download_url" : "https://cpan.metacpan.org/authors/id/L/LB/LBROCARD/perl5.005_04-RC2.tar.gz", "author" : "LBROCARD", "date" : "2004-02-18T14:20:15" } ], "took" : 30, "total" : 418 } EOF } installation2.t000644000765000024 605213614277060 16706 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; use Test::Exception; require 'test_helpers.pl'; use Test::Spec; ## setup ## note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; describe "App::perlbrew" => sub { describe "->do_install_url method" => sub { it "should accept an URL to perl tarball, and download the tarball." => sub { my $app = App::perlbrew->new; my @expectations; push @expectations, App::perlbrew->expects("http_download")->returns(0); push @expectations, $app->expects("do_extract_tarball")->returns(""); push @expectations, $app->expects("do_install_this")->returns(""); $app->do_install_url("http://example.com/perl-5.14.0.tar.gz"); for(@expectations) { ok $_->verify; } pass; } }; describe "->do_install_archive method" => sub { it "accepts a path to perl tarball and perform installation process." => sub { my $app = App::perlbrew->new; my $e1 = $app->expects("do_extract_tarball")->returns(App::Perlbrew::Path->new ("/a/fake/path/to/perl-5.12.3")); my $e2 = $app->expects("do_install_this")->returns(""); $app->do_install_archive(App::Perlbrew::Path->new ("/a/fake/path/to/perl-5.12.3.tar.gz")); ok $e1->verify, "do_extract_tarball is called"; ok $e2->verify, "do_install_this is called"; pass; } }; describe "->do_install_this method" => sub { it "should log successful brews to the log_file." => sub { my $app = App::perlbrew->new; $app->{dist_extracted_dir} = ''; $app->{dist_name} = ''; my %expectations = ( 'do_system' => $app->expects("do_system")->returns(1), ); $app->do_install_this('', '5.12.3', 'perl-5.12.3'); open(my $log_handle, '<', $app->{log_file}); like(<$log_handle>, qr/##### Brew Finished #####/, 'Success message shows in log'); foreach my $sub_name (keys %expectations) { ok $expectations{$sub_name}->verify, "$sub_name is called"; } }; it "should log brew failure to the log_file if system call fails." => sub { my $app = App::perlbrew->new; $app->{dist_extracted_dir} = ''; $app->{dist_name} = ''; my %expectations = ( 'do_system' => $app->expects("do_system")->returns(0), ); throws_ok( sub {$app->do_install_this('', '5.12.3', 'perl-5.12.3')}, qr/Installation process failed/); open(my $log_handle, '<', $app->{log_file}); like(<$log_handle>, qr/##### Brew Failed #####/, 'Failure message shows in log'); foreach my $sub_name (keys %expectations) { ok $expectations{$sub_name}->verify, "$sub_name is called"; } }; } }; runtests unless caller; 17.release-detail-cperl-local.t000644000765000024 117413614277060 21424 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; my $app = App::perlbrew->new(); my $rd = { type => "cperl", "version" => "5.22.2" }; $app->release_detail_cperl_local("cperl-5.22.2", $rd); ok defined( $rd->{tarball_url} ); ok defined( $rd->{tarball_name} ); is $rd->{tarball_url}, "https://github.com/perl11/cperl/releases/download/cperl-5.22.2/cperl-5.22.2.tar.gz"; is $rd->{tarball_name}, "cperl-5.22.2.tar.gz"; done_testing; Installations.pm000644000765000024 100713614277060 22614 0ustar00gugodstaff000000000000App-perlbrew-0.88/lib/App/Perlbrew/Path use strict; use warnings; package App::Perlbrew::Path::Installations; require App::Perlbrew::Path; require App::Perlbrew::Path::Installation; our @ISA = qw( App::Perlbrew::Path ); sub child { my ($self, @params) = @_; my $return = $self; $return = $return->_child ('App::Perlbrew::Path::Installation' => shift @params) if @params; $return = $return->child (@params) if @params; $return; } sub children { shift->_children ('App::Perlbrew::Path::Installation' => @_); } sub list { shift->children; } 1; builddir.t000644000765000024 245113614277060 15720 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Spec; sub looks_like_perlbrew_builddir; describe "App::perlbrew#builddir method" => sub { it "should return path in \$App::perlbrew::PERLBREW_ROOT normally" => sub { local $App::perlbrew::PERLBREW_ROOT = '/perlbrew/root'; my $app = App::perlbrew->new; looks_like_perlbrew_builddir $app->builddir, '/perlbrew/root/build'; }; it "should return path relative to root" => sub { my $app = App::perlbrew->new; $app->root("/fnord"); looks_like_perlbrew_builddir $app->builddir, "/fnord/build"; }; }; describe "App::perlbrew->new" => sub { it "should accept --builddir args" => sub { local $App::perlbrew::PERLBREW_ROOT = '/perlbrew/root'; my $app = App::perlbrew->new("--builddir" => "/perlbrew/buildroot"); looks_like_perlbrew_builddir $app->builddir, "/perlbrew/buildroot"; }; }; runtests unless caller; sub looks_like_perlbrew_builddir { my ($got, $expected) = @_; my ($ok, $stack); ($ok, $stack) = Test::Deep::cmp_details "$got", "$expected"; unless ($ok) { fail; diag Test::Deep::deep_diag $stack; return; } return Test::Deep::cmp_deeply $got, Isa ('App::Perlbrew::Path'); } metamerge.json000644000765000024 36313614277060 16313 0ustar00gugodstaff000000000000App-perlbrew-0.88{ "x_static_install": true, "resources": { "repository": { "web": "https://github.com/gugod/App-perlbrew", "url": "https://github.com/gugod/App-perlbrew.git", "type": "git" } } } test_helpers.pl000644000765000024 352713614277060 17000 0ustar00gugodstaff000000000000App-perlbrew-0.88/t=begin yada yada Copy this snippet to the beginning of tests: use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; tldr: This file should be `require`-ed after the "use App::perlbrew;" statement in the test. It is meant to override subroutines for testing purposes and not mess up developer's own perlbrew environment. `FindBin` should be used to put 't/' dir to `@INC`. =cut use strict; use Test::More; use IO::All; use File::Temp qw( tempdir ); sub dir { App::Perlbrew::Path->new (@_); } sub file { App::Perlbrew::Path->new (@_); } $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; delete $ENV{PERLBREW_LIB}; my $root = App::Perlbrew::Path::Root->new ($ENV{PERLBREW_ROOT}); $root->perls->mkpath; $root->build->mkpath; $root->dists->mkpath; no warnings 'redefine'; sub App::perlbrew::do_install_release { my ($self, $name) = @_; $name = $self->{as} if $self->{as}; my $root = $self->root; my $installation_dir = $root->perls ($name); $self->{installation_name} = $name; $installation_dir->mkpath; $root->perls ($name, "bin")->mkpath; my $perl = $root->perls ($name, "bin")->child ("perl"); io($perl)->print(<<'CODE'); #!/usr/bin/env perl use File::Basename; my $name = basename(dirname(dirname($0))), "\n"; $name =~ s/^perl-//; my ($a,$b,$c) = split /\./, $name; printf('%d.%03d%03d' . "\n", $a, $b, $c); CODE chmod 0755, $perl; note "(mock) installed $name to $installation_dir"; } sub mock_perlbrew_install { my ($name, @args) = @_; App::perlbrew->new(install => $name, @args)->run(); } sub mock_perlbrew_lib_create { my $name = shift; App::Perlbrew::Path ->new ($App::perlbrew::PERLBREW_HOME, "libs", $name) ->mkpath ; } 1; command-available.t000644000765000024 534713614277060 17465 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use File::Temp qw( tempdir ); use Test::Output; use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 ); # # This is an example of availables perls on fluca1978 machine 2017-10-05. # my %available_perls = ( 'perl-5.27.4' => 'http://www.cpan.org/src/5.0/perl-5.27.4.tar.gz', 'perl-5.26.1' => 'http://www.cpan.org/src/5.0/perl-5.26.1.tar.gz', 'perl-5.24.3' => 'http://www.cpan.org/src/5.0/perl-5.24.3.tar.gz', 'perl-5.22.4' => 'http://www.cpan.org/src/5.0/perl-5.22.4.tar.gz', 'perl-5.20.3' => 'http://www.cpan.org/src/5.0/perl-5.20.3.tar.gz', 'perl-5.18.4' => 'http://www.cpan.org/src/5.0/perl-5.18.4.tar.gz', 'perl-5.16.3' => 'http://www.cpan.org/src/5.0/perl-5.16.3.tar.gz', 'perl-5.14.4' => 'http://www.cpan.org/src/5.0/perl-5.14.4.tar.gz', 'perl-5.12.5' => 'http://www.cpan.org/src/5.0/perl-5.12.5.tar.gz', 'perl-5.10.1' => 'http://www.cpan.org/src/5.0/perl-5.10.1.tar.gz', 'perl-5.8.9' => 'http://www.cpan.org/src/5.0/perl-5.8.9.tar.gz', 'perl-5.6.2' => 'http://www.cpan.org/src/5.0/perl-5.6.2.tar.gz', 'perl5.005_04' => 'http://www.cpan.org/src/5.0/perl5.005_04.tar.gz', 'perl5.004_05' => 'http://www.cpan.org/src/5.0/perl5.004_05.tar.gz', 'cperl-5.26.1' => 'https://github.com/perl11/cperl/archive/cperl-5.26.1.tar.gz', 'cperl-5.27.1' => 'https://github.com/perl11/cperl/archive/cperl-5.27.1.tar.gz', ); describe "available command output, when nothing installed locally," => sub { it "should display a list of perl versions" => sub { my $app = App::perlbrew->new("available", '--verbose'); $app->expects( 'available_perls_with_urls' )->returns( \%available_perls ); stdout_like sub { $app->run(); }, qr/^\s{3,}c?perl-?\d\.\d{1,3}[_.]\d{1,2}\s+(available from)\s+/, 'Cannot find Perl in output' }; }; describe "available command output, when something installed locally," => sub { it "should display a list of perl versions, with markers on installed versions" => sub { my $app = App::perlbrew->new("available", '--verbose'); my @installed_perls = ( { name => "perl-5.24.0" }, { name => "perl-5.20.3" } ); $app->expects( 'available_perls_with_urls' )->returns( \%available_perls ); $app->expects("installed_perls")->returns(@installed_perls); stdout_like sub { $app->run(); }, qr/^i?\s{2,}c?perl-?\d\.\d{1,3}[_.]\d{1,2}\s+(INSTALLED on .* via|available from)\s+/, 'Cannot find Perl in output' }; }; runtests unless caller; 08.error_available.t000644000765000024 53513614277060 17462 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use lib qw(lib); use App::perlbrew; use Test::More; use Test::Exception; no warnings 'redefine'; sub App::perlbrew::http_get { "" } throws_ok( sub { my $app = App::perlbrew->new("available"); $app->run; }, qr[ERROR: Unable to retrieve the list of perls.] ); done_testing; app-perlbrew-path.t000644000765000024 1575613614277060 17510 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use File::Temp qw[]; use Test::Spec; use Test::Exception; use Test::Deep; use App::Perlbrew::Path; sub looks_like_perlbrew_path; sub arrange_testdir; describe "App::Perlbrew::Path" => sub { describe "new()" => sub { it "should accept one parameter" => sub { my $path = App::Perlbrew::Path->new ("foo/bar/baz"); cmp_deeply $path, looks_like_perlbrew_path "foo/bar/baz"; }; it "should concatenate multiple parameters into single path" => sub { my $path = App::Perlbrew::Path->new ("foo", "bar/baz"); cmp_deeply $path, looks_like_perlbrew_path "foo/bar/baz"; }; it "should die with undefined element" => sub { throws_ok { App::Perlbrew::Path->new ('foo', undef, 'bar') } qr/^Received an undefined entry as a parameter/, ''; }; it "should concatenate long (root) path" => sub { my $path = App::Perlbrew::Path->new ('', qw(this is a long path to check if it is joined ok)); cmp_deeply $path, looks_like_perlbrew_path '/this/is/a/long/path/to/check/if/it/is/joined/ok'; }; }; describe "basename()" => sub { it "should return basename" => sub { my $path = App::Perlbrew::Path->new ("foo/bar/baz.tar.gz"); is $path->basename, "baz.tar.gz"; }; it "should trim provided suffix match" => sub { my $path = App::Perlbrew::Path->new ("foo/bar/baz.tar.gz"); is $path->basename (qr/\.tar\.(?:gz|bz2|xz)$/), "baz"; }; }; describe "child()" => sub { it "should create direct child" => sub { my $path = App::Perlbrew::Path->new ("foo/bar")->child (1); cmp_deeply $path, looks_like_perlbrew_path "foo/bar/1"; }; it "should accept multiple children" => sub { my $path = App::Perlbrew::Path->new ("foo/bar")->child (1, 2); cmp_deeply $path, looks_like_perlbrew_path "foo/bar/1/2"; }; it "should return chainable object" => sub { my $path = App::Perlbrew::Path->new ("foo/bar")->child (1, 2)->child (3); cmp_deeply $path, looks_like_perlbrew_path "foo/bar/1/2/3"; }; }; describe "children()" => sub { it "should return empty list on empty match" => sub { my $root = arrange_testdir; cmp_deeply [ $root->children ], []; }; it "should return Path instances" => sub { my $root = arrange_testdir; $root->child ($_)->mkpath for qw[ aa ab ba ]; cmp_deeply [ $root->children ], [ looks_like_perlbrew_path ($root->child ('aa')->stringify), looks_like_perlbrew_path ($root->child ('ab')->stringify), looks_like_perlbrew_path ($root->child ('ba')->stringify), ]; }; }; describe "mkpath()" => sub { it "should create recursive path" => sub { my $path = arrange_testdir ("foo/bar/baz"); $path->mkpath; ok -d $path; }; it "should not die when path already exists" => sub { my $path = arrange_testdir ("foo/bar/baz"); $path->mkpath; lives_ok { $path->mkpath }; }; it "should return self" => sub { my $path = arrange_testdir ("foo/bar/baz"); cmp_deeply $path->mkpath, looks_like_perlbrew_path "$path"; }; }; describe "readlink()" => sub { my $test_root; my $link; before each => sub { $test_root = arrange_testdir; $link = $test_root->child ('link'); }; context "when path doesn't exist" => sub { it "should return undef" => sub { is $link->readlink, undef; }; }; context "when path isn't a symlink" => sub { before each => sub { $link->mkpath }; it "should return undef" => sub { is $link->readlink, undef; }; }; context "should return path object of link content" => sub { my $dest; before each => sub { $dest = $test_root->child ('dest'); $dest->mkpath; symlink $dest, $link; }; it "should return link path" => sub { my $read = $link->readlink; cmp_deeply $read, looks_like_perlbrew_path "$dest"; }; }; }; describe "rmpath()" => sub { it "should remove path recursively" => sub { my $path = arrange_testdir ("foo"); my $child = $path->child ("bar/baz"); $child->mkpath; $path->rmpath; ok ! -d $path; }; it "should not die when path doesn't exist" => sub { my $path = arrange_testdir ("foo"); lives_ok { $path->rmpath }; }; it "should return self" => sub { my $path = arrange_testdir ("foo/bar/baz"); cmp_deeply $path, looks_like_perlbrew_path "$path"; }; }; describe "stringify_with_tilde" => sub { it "should expand leading homedir" => sub { local $ENV{HOME} = "/home/perlbrew"; my $path = App::Perlbrew::Path->new ("/home/perlbrew/.root"); is $path->stringify_with_tilde, "~/.root"; }; it "should not expand leading homedir prefix" => sub { local $ENV{HOME} = "/home/perlbrew"; my $path = App::Perlbrew::Path->new ("/home/perlbrew-stable/.root"); is $path->stringify_with_tilde, "/home/perlbrew-stable/.root"; }; }; describe "symlink()" => sub { it "should create symlink" => sub { my $root = arrange_testdir; my $file = $root->child ('file'); open my $fh, '>>', $file or die $!; my $symlink = $file->symlink ($root->child ('symlink')); unless ($symlink) { fail; diag "Symlink failed: $!"; return; } unless ($symlink eq $root->child ("symlink")) { fail; diag "is should return symlink object"; diag "got : $symlink"; diag "expected: $root/symlink"; return; } my $readlink = $symlink->readlink; unless ($readlink eq $file) { fail; diag "it should point to origin file"; diag "got : $readlink"; diag "expected: $root/file"; return; } pass; }; it "should replace existing file in force mode" => sub { my $root = arrange_testdir; my $file = $root->child ('file'); open my $fh, '>>', $file or die $!; $root->child ('foo')->symlink ($root->child ('symlink')) or diag "init failed: $!"; my $symlink = $file->symlink ($root->child ('symlink'), 'force'); unless ($symlink) { fail; diag "Symlink failed: $!"; return; } unless ($symlink eq $root->child ("symlink")) { fail; diag "is should return symlink object"; diag "got : $symlink"; diag "expected: $root/symlink"; return; } my $readlink = $symlink->readlink; unless ($readlink eq $file) { fail; diag "it should point to origin file"; diag "got : $readlink"; diag "expected: $root/file"; return; } pass; }; }; describe "unlink()" => sub { it "should not report failure if file doesn't exist" => sub { my $root = arrange_testdir; my $file = $root->child ('file'); $file->unlink; ok ! -e $file; }; it "should remove file" => sub { my $root = arrange_testdir; my $file = $root->child ('file'); open my $fh, '>>', $file or die $!; fail and diag ("file doesn't exist yet") and return unless -e $file; $file->unlink; ok ! -e $file; }; }; return; }; runtests unless caller; sub looks_like_perlbrew_path { my ($expected) = @_; all ( methods (stringify => $expected), obj_isa ('App::Perlbrew::Path'), ); } sub arrange_testdir { my (@path) = @_; App::Perlbrew::Path->new (File::Temp::tempdir (CLEANUP => 1), @path); } README000644000765000024 1431513614277060 14374 0ustar00gugodstaff000000000000App-perlbrew-0.88NAME App::perlbrew - Manage perl installations in your $HOME SYNOPSIS # Installation curl -L https://install.perlbrew.pl | bash # Initialize perlbrew init # See what is available perlbrew available # Install some Perls perlbrew install 5.18.2 perlbrew install perl-5.8.1 perlbrew install perl-5.19.9 # See what were installed perlbrew list # Swith to an installation and set it as default perlbrew switch perl-5.18.2 # Temporarily use another version only in current shell. perlbrew use perl-5.8.1 perl -v # Or turn it off completely. Useful when you messed up too deep. # Or want to go back to the system Perl. perlbrew off # Use 'switch' command to turn it back on. perlbrew switch perl-5.12.2 # Exec something with all perlbrew-ed perls perlbrew exec -- perl -E 'say $]' DESCRIPTION perlbrew is a program to automate the building and installation of perl in an easy way. It provides multiple isolated perl environments, and a mechanism for you to switch between them. Everything are installed unter ~/perl5/perlbrew. You then need to include a bashrc/cshrc provided by perlbrew to tweak the PATH for you. You then can benefit from not having to run sudo commands to install cpan modules because those are installed inside your HOME too. For the documentation of perlbrew usage see perlbrew command on MetaCPAN , or by running perlbrew help, or by visiting perlbrew's official website . The following documentation features the API of App::perlbrew module, and may not be remotely close to what your want to read. INSTALLATION It is the simplest to use the perlbrew installer, just paste this statement to your terminal: curl -L https://install.perlbrew.pl | bash Or this one, if you have fetch (default on FreeBSD): fetch -o- https://install.perlbrew.pl | sh After that, perlbrew installs itself to ~/perl5/perlbrew/bin, and you should follow the instruction on screen to modify your shell rc file to put it in your PATH. The installed perlbrew command is a standalone executable that can be run with system perl. The minimum system perl version requirement is 5.8.0, which should be good enough for most of the OSes these days. A fat-packed version of patchperl is also installed to ~/perl5/perlbrew/bin, which is required to build old perls. The directory ~/perl5/perlbrew will contain all install perl executables, libraries, documentations, lib, site_libs. In the documentation, that directory is referred as perlbrew root. If you need to set it to somewhere else because, say, your HOME has limited quota, you can do that by setting PERLBREW_ROOT environment variable before running the installer: export PERLBREW_ROOT=/opt/perl5 curl -L https://install.perlbrew.pl | bash As a result, different users on the same machine can all share the same perlbrew root directory (although only original user that made the installation would have the permission to perform perl installations.) You may also install perlbrew from CPAN: cpan App::perlbrew In this case, the perlbrew command is installed as /usr/bin/perlbrew or /usr/local/bin/perlbrew or others, depending on the location of your system perl installation. Please make sure not to run this with one of the perls brewed with perlbrew. It's the best to turn perlbrew off before you run that, if you're upgrading. perlbrew off cpan App::perlbrew You should always use system cpan (like /usr/bin/cpan) to install App::perlbrew because it will be installed under a system PATH like /usr/bin, which is not affected by perlbrew switch or use command. The self-upgrade command will not upgrade the perlbrew installed by cpan command, but it is also easy to upgrade perlbrew by running cpan App::perlbrew again. METHODS (Str) current_perl Return the "current perl" object attribute string, or, if absent, the value of PERLBREW_PERL environment variable. (Str) current_perl (Str) Set the current_perl object attribute to the given value. PROJECT DEVELOPMENT perlbrew project uses github https://github.com/gugod/App-perlbrew/issues and RT for issue tracking. Issues sent to these two systems will eventually be reviewed and handled. See https://github.com/gugod/App-perlbrew/contributors for a list of project contributors. AUTHOR Kang-min Liu COPYRIGHT Copyright (c) 2010- Kang-min Liu . LICENCE The MIT License DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. perlbrew000644000765000024 4750013614277060 16567 0ustar00gugodstaff000000000000App-perlbrew-0.88/script#!/usr/bin/perl use strict; use App::perlbrew; my $app = App::perlbrew->new(@ARGV); $app->run(); __END__ =head1 NAME perlbrew - Perl environment manager. =head1 SYNOPSIS perlbrew command syntax: perlbrew [options] [arguments] Commands: init Initialize perlbrew environment. info Show useful information about the perlbrew installation install Install perl uninstall Uninstall the given installation available List perls available to install lib Manage local::lib directories. alias Give perl installations a new name upgrade-perl Upgrade the current perl list List perl installations use Use the specified perl in current shell off Turn off perlbrew in current shell switch Permanently use the specified perl as default switch-off Permanently turn off perlbrew (revert to system perl) exec exec programs with specified perl environments. clone-modules re-installs all CPAN modules from one installation to another self-install Install perlbrew itself under PERLBREW_ROOT/bin self-upgrade Upgrade perlbrew itself. install-patchperl Install patchperl install-cpanm Install cpanm, a friendly companion. install-multiple Install multiple versions and flavors of perl download Download the specified perl distribution tarball. clean Purge tarballs and build directories version Display version help Read more detailed instructions Generic command options: -q --quiet Be quiet on informative output message. -v --verbose Tell me more about it. See `perlbrew help` for the full documentation of perlbrew, or See `perlbrew help ` for detail description of the command. =head1 CONFIGURATION =over 4 =item PERLBREW_ROOT By default, perlbrew builds and installs perls into C<$ENV{HOME}/perl5/perlbrew> directory. To use a different directory, set this environment variable in your C to the directory in your shell RC before sourcing perlbrew's RC. It is possible to share one perlbrew root with multiple user account on the same machine. Therefore people do not have to install the same version of perl over an over. Let's say C is the directory we want to share. All users should be able append this snippet to their bashrc to make it effective: export PERLBREW_ROOT=/opt/perl5 source ${PERLBREW_ROOT}/etc/bashrc After doing so, everyone's PATH should include C and C. Each user can invoke C and C to independently switch to different perl environment of their choice. However, only the user with write permission to C<$PERLBREW_ROOT> may install CPAN modules. This is both good and bad depending on the working convention of your team. If you wish to install CPAN modules only for yourself, you should use the C command to construct a personal local::lib environment. local::lib environments are personal, and are not shared between different users. For more detail, read C and the documentation of L. If you want even a cooler module isolation and wish to install CPAN modules used for just one project, you should use L for this purpose. It is also possible to set this variable before installing perlbrew to make perlbrew install itself under the given PERLBREW_ROOT: export PERLBREW_ROOT=/opt/perl5 curl -L http://install.perlbrew.pl | bash After doing this, the perlbrew executable is installed as C =item PERLBREW_HOME By default, perlbrew stores per-user setting to C<$ENV{HOME}/.perlbrew> directory. To use a different directory, set this environment variable in your shell RC before sourcing perlbrew's RC. In some cases, say, your home directory is on NFS and shared across multiple machines, you may wish to have several different perlbrew setting per-machine. To do so, you can use the C environment variable to tell perlbrew where to look for the initialization file. Here's a brief bash snippet for the given scenario. if [ "$(hostname)" == "machine-a" ]; then export PERLBREW_HOME=~/.perlbrew-a elif [ "$(hostname)" == "machine-b" ]; then export PERLBREW_HOME=~/.perlbrew-b fi source ~/perl5/perlbrew/etc/bashrc =item PERLBREW_CONFIGURE_FLAGS This environment variable specify the list of command like flags to pass through to 'sh Configure'. By default it is '-de'. =item PERLBREW_CPAN_MIRROR The CPAN mirror url of your choice. The default value is "http://www.cpan.org" =back =head1 COMMAND: INIT Usage: perlbrew init The C command should be manually invoked whenever you (the perlbrew user) upgrade or reinstall perlbrew. If the upgrade is done with C command, or by running the one-line installer manually, this command is invoked automatically. =head1 COMMAND: INFO =over 4 =item B [module] Usage: perlbrew info [ ] Display useful information about the perlbrew installation. If a module is given the version and location of the module is displayed. =back =head1 COMMAND: INSTALL =over 4 =item B [options] perl- =item B [options] Build and install the given version of perl. Version numbers usually look like "5.x.xx", or "perl-5.xx.x-RCx" for release candidates. The specified perl is downloaded from the official CPAN website or from the mirror site configured before. Add '--mirror $URL' to specify the URL of mirror site. =item B [options] cperl- Install the cperl distribution released from: https://github.com/perl11/cperl/releases See http://perl11.org/cperl/ for more information about cperl distribution. =item B [options] perl-stable =item B [options] stable A convenient way to install the most recent stable version of Perl, of those that are available. =item B [options] perl-blead =item B [options] blead A special way to install the blead version of perl, which is downloaded from this specific URL regardless of mirror settings: http://perl5.git.perl.org/perl.git/snapshot/blead.tar.gz =item B [options] /path/to/perl/git/checkout/dir Build and install from the given git checkout dir. =item B [options] /path/to/perl-5.14.0.tar.gz Build and install from the given archive file. =item B [options] http://example.com/mirror/perl-5.12.3.tar.gz Build and install from the given URL. Supported URL schemes are C, C, C and C. =back Options for C command: -f --force Force installation -j $n Parallel building and testing. ex. C -n --notest Skip testing --switch Automatically switch to this Perl once successfully installed, as if with `perlbrew switch ` --as Install the given version of perl by a name. ex. C --noman Skip installation of manpages --thread Build perl with usethreads enabled --multi Build perl with usemultiplicity enabled --64int Build perl with use64bitint enabled --64all Build perl with use64bitall enabled --ld Build perl with uselongdouble enabled --debug Build perl with DEBUGGING enabled --clang Build perl using the clang compiler --no-patchperl Skip calling patchperl -D,-U,-A Switches passed to perl Configure script. ex. C --destdir $path Install perl as per 'make install DESTDIR=$path' --sitecustomize $filename Specify a file to be installed as sitecustomize.pl By default, all installations are configured after their name like this: sh Configure -de -Dprefix=$PERLBREW_ROOT/perls/ =head1 COMMAND: INSTALL-MULTIPLE Usage: perlbrew install-multiple [options] ... Build and install the given versions of perl. C accepts the same set of options as the command C plus the following ones: --both $flavor Where $flavor is one of C, C, C, C<64int>, C<64all>, C and C. For every given perl version, install two flavors, one with the flag C<--$flavor> set and the other with out. C<--both> can be passed multiple times with different values and in that case, all the possible combinations are generated. --common-variations equivalent to C<--both thread --both ld --both 64int> --all-variations generates all the possible flavor combinations --append $string Appends the given string to the generated names For instance: perlbrew install-multiple 5.18.0 blead --both thread --both debug Installs the following perls: perl-blead perl-blead-debug perl-blead-thread-multi perl-blead-thread-multi-debug perl-5.18.0 perl-5.18.0-debug perl-5.18.0-thread-multi perl-5.18.0-thread-multi-debug (note that the C flavor is selected automatically because C requires it) Another example using custom compilation flags: perlbrew install-multiple 5.18.0 --both thread -Doptimize='-O3' --append='-O3' =head1 COMMAND: UNINSTALL Usage: perlbrew uninstall Uninstalls the given perl installation. The name is the installation name as in the output of `perlbrew list`. This effectively deletes the specified perl installation, and all libs associated with it. =head1 COMMAND: USE Usage: perlbrew B [perl- | | ] Use the given version perl in current shell. This will not effect newly opened shells. Without a parameter, shows the version of perl currently in use. =head1 COMMAND: SWITCH Usage: perlbrew switch [ ] Switch to the given version, and makes it the default for this and all future terminal sessions. Without a parameter, shows the version of perl currently selected. =head1 COMMAND: LIST Usage: perlbrew list List all perl installations inside perlbrew root specified by C<$PERLBREW_ROOT> environment variable. By default, the value is C<~/perl5/perlbrew>. If there are libs associated to some perl installations, they will be included as part of the name. The output items in this list can be the argument in various other commands. =head1 COMMAND: AVAILABLE Usage: perlbrew available [--all] List the recently available versions of perl on CPAN. The list is retrieved from the web page L, and is not the list of *all* perl versions ever released in the past. To get a list of all perls ever released, use the C<--all> option. NOTICE: This command might be gone in the future and become an option of 'list' command. =head1 COMMAND: OFF Usage: perlbrew off Temporarily disable perlbrew in the current shell. Effectively re-enables the default system Perl, whatever that is. This command works only if you add the statement of `source $PERLBREW_ROOT/etc/bashrc` in your shell initialization (bashrc / zshrc). =head1 COMMAND: SWITCH-OFF Usage: perlbrew switch-off Permananently disable perlbrew. Use C command to re-enable it. Invoke C command to enable it only in the current shell. Re-enables the default system Perl, whatever that is. =head1 COMMAND: ALIAS Usage: perlbrew alias [-f] create Create an alias for the installation named . Usage: perlbrew alias [-f] rename Rename the alias to a new name. Usage: perlbrew alias delete Delete the given alias. =head1 COMMAND: EXEC Usage: perlbrew exec [options] Options for C command: --with perl-version,... - only use these versions --min n.nnnnn - minimum perl version (format is the same as in 'use 5.012') --max n.nnnnn - maximum perl version --halt-on-error - stop on first nonzero exit status Execute command for each perl installations, one by one. For example, run a Hello program: perlbrew exec perl -e 'print "Hello from $]\n"' The output looks like this: perl-5.12.2 ========== Hello word from perl-5.012002 perl-5.13.10 ========== Hello word from perl-5.013010 perl-5.14.0 ========== Hello word from perl-5.014000 Notice that the command is not executed in parallel. When C<--with> argument is provided, the command will be only executed with the specified perl installations. The following command install Moose module into perl-5.12, regardless the current perl: perlbrew exec --with perl-5.12 cpanm Moose Multiple installation names can be provided: perlbrew exec --with perl-5.12,perl-5.12-debug,perl-5.14.2 cpanm Moo They are split by either spaces or commas. When spaces are used, it is required to quote the whole specification as one argument, but then commas can be used in the installation names: perlbrew exec --with '5.12 5.12,debug 5.14.2@nobita @shizuka' cpanm Moo As demonstrated above, "perl-" prefix can be omitted, and lib names can be specified too. Lib names can appear without a perl installation name, in such cases it is assumed to be "current perl". At the moment, any specified names that fails to be resolved as a real installation names are silently ignored in the output. Also, the command exit status are not populated back. =head1 COMMAND: ENV Usage: perlbrew env [ ] Low-level command. Invoke this command to see the list of environment variables that are set by C itself for shell integration. The output is something similar to this (if your shell is bash/zsh): export PERLBREW_ROOT=/Users/gugod/perl5/perlbrew export PERLBREW_VERSION=0.31 export PERLBREW_PATH=/Users/gugod/perl5/perlbrew/bin:/Users/gugod/perl5/perlbrew/perls/current/bin export PERLBREW_PERL=perl-5.14.1 tcsh / csh users should see 'setenv' statements instead of `export`. =head1 COMMAND: SYMLINK-EXECUTABLES Usage: perlbrew symlink-executables [ ] Low-level command. This command is used to create the C executable symbolic link to, say, C. This is only required for development version of perls. You don't need to do this unless you have been using old perlbrew to install perls, and you find yourself confused because the perl that you just installed appears to be missing after invoking `use` or `switch`. perlbrew changes its installation layout since version 0.11, which generates symlinks to executables in a better way. If you just upgraded perlbrew (from 0.11 or earlier versions) and C failed to work after you switch to a development release of perl, say, perl-5.13.6, run this command: perlbrew symlink-executables perl-5.13.6 This essentially creates this symlink: ${PERLBREW_ROOT}/perls/perl-5.13.6/bin/perl -> ${PERLBREW_ROOT}/perls/perl-5.13.6/bin/perl5.13.6 Newly installed perls, whether they are development versions or not, does not need manually treatment with this command. =head1 COMMAND: INSTALL-CPANM Usage: perlbrew install-cpanm Install the C standalone executable in C<$PERLBREW_ROOT/bin>. For more rationale about the existence of this command, read =head1 COMMAND: INSTALL-PATCHPERL Usage: perlbrew install-patchperl Install the C standalone executable in C<$PERLBREW_ROOT/bin>. This is automatically invoked if your perlbrew installation is done with the installer, but not with cpan. For more rationale about the existence of this command, read =head1 COMMAND: SELF-UPGRADE Usage: perlbrew self-upgrade This command upgrades Perlbrew to its latest version. =head1 COMMAND: SELF-INSTALL Usage: perlbrew self-install NOTICE: You should not need to run this command in your daily routine. This command installs perlbrew itself to C<$PERLBREW_ROOT/bin>. It is intended to be used by the perlbrew installer. However, you could manually do the following to re-install only the C executable: curl https://raw.githubusercontent.com/gugod/App-perlbrew/master/perlbrew -o perlbrew perl ./perlbrew self-install It is slightly different from running the perlbrew installer because C is not installed in this case. =head1 COMMAND: CLEAN Usage: perlbrew clean Removes all previously downloaded Perl tarballs and build directories. =head1 COMMAND: VERSION Usage: perlbrew version Show the version of perlbrew. =head1 COMMAND: LIB Usage: perlbrew lib perlbrew lib list perlbrew lib create perlbrew lib delete The `lib` command is used to manipulate local::lib roots inside perl installations. Effectively it is similar to `perl -Mlocal::lib=/path/to/lib-name`, but a little bit more than just that. A lib name can be a short name, containing alphanumeric, like 'awesome', or a full name, prefixed by a perl installation name and a '@' sign, for example, 'perl-5.14.2@awesome'. Here are some a brief examples to invoke the `lib` command: # Create lib perl-5.12.3@shizuka perlbrew lib create perl-5.12.3@shizuka # Create lib perl-5.14.2@nobita and perl-5.14.2@shizuka perlbrew use perl-5.14.2 perlbrew lib create nobita perlbrew lib create shizuka # See the list of use/switch targets perlbrew list # Activate a lib in current shell perlbrew use perl-5.12.3@shizuka perlbrew use perl-5.14.2@nobita perlbrew use perl-5.14.2@shizuka # Activate a lib as default perlbrew switch perl-5.12.3@shizuka perlbrew switch perl-5.14.2@nobita perlbrew switch perl-5.14.2@shizuka # Delete lib perl-5.14.2@nobita and perl-5.14.2@shizuka perlbrew use perl-5.14.2 perlbrew lib delete nobita perlbrew lib delete shizuka # Delete lib perl-5.12.3@shizuka perlbrew lib delete perl-5.12.3@shizuka Short lib names are local to current perl. A lib name 'nobita' can refer to 'perl-5.12.3@nobita' or 'perl-5.14.2@nobita', depending on your current perl. When Cing or Cing to a lib, always provide the long name. A simple rule: the argument to C or C command should appear in the output of C. =head1 COMMAND: UPGRADE-PERL Usage: perlbrew upgrade-perl Minor Perl releases (ex. 5.x.*) are binary compatible with one another, so this command offers you the ability to upgrade older perlbrew environments in place. It upgrades the currently activated perl to its latest released brothers. If you have a shell with 5.14.0 activated, it upgrades it to 5.14.2. =head1 COMMAND: DOWNLOAD Usage: perlbrew download perl-5.14.2 perlbrew download perl-5.16.1 perlbrew download perl-5.17.3 Download the specified version of perl distribution tarball under C<< $PERLBREW_ROOT/dists/ >> directory. =head1 COMMAND: LIST-MODULES List all installed cpan modules for the current perl. This command can be used in conjunction with `perlbrew exec` to migrate your module installation to different perl. The following command re-installs all modules under perl-5.16.0: perlbrew list-modules | perlbrew exec --with perl-5.16.0 cpanm Note that this installs the I versions of the Perl modules on the new perl, which are not necessarily the I module versions you had installed previously. =head1 COMMAND: CLONE-MODULES This command re-installs all CPAN modules found from one installation to another. Usage: perlbrew clone-modules for example perlbrew clone-modules 5.26.1 5.27.7 =head1 SEE ALSO L, L, L =cut 00.load.t000644000765000024 15013614277060 15231 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use Test::More tests => 1; use lib qw(lib); use_ok('App::perlbrew'); curl000644000765000024 23413614277060 16256 0ustar00gugodstaff000000000000App-perlbrew-0.88/t/fake-bin#!/bin/sh exit 127 # This fake curl script is created to avoid # App::perlbrew::http_user_agent_program() from selecting "curl" as # the http ua program. 08.error_install.t000644000765000024 143113614277060 17224 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use lib qw(lib); use Test::More; use Test::Exception; use File::Temp qw(tempdir); use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; App::Perlbrew::Path->new ($ENV{PERLBREW_ROOT})->child ("perls")->mkpath; App::Perlbrew::Path->new ($ENV{PERLBREW_ROOT})->child ("build")->mkpath; App::Perlbrew::Path->new ($ENV{PERLBREW_ROOT})->child ("dists")->mkpath; no warnings 'redefine'; sub App::perlbrew::http_download { return "ERROR" } throws_ok( sub { my $app = App::perlbrew->new("install", "perl-5.12.3"); $app->run; }, qr[ERROR: Failed to download .*perl-5.12.3.*] ); done_testing; PERL-LICENSE000644000765000024 4737113614277060 16036 0ustar00gugodstaff000000000000App-perlbrew-0.88/doc Terms of Perl itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" ---------------------------------------------------------------------------- The General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ---------------------------------------------------------------------------- The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End 04.find_available_perls.t000644000765000024 1127413614277060 20514 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::More; use App::perlbrew; plan tests => 52; my $html = <
ReleaseFileTypeAge
5.135.13.11perl-5.13.11.tar.gz, perl-5.13.11.tar.bz2devel14 days
5.125.12.3perl-5.12.3.tar.gz, perl-5.12.3.tar.bz2maint2 months, 11 days
5.105.10.1perl-5.10.1.tar.gz, perl-5.10.1.tar.bz2maint1 year, 7 months
5.85.8.9perl-5.8.9.tar.gz, perl-5.8.9.tar.bz2maint2 years, 3 months
5.65.6.2perl-5.6.2.tar.gzmaint7 years, 4 months
5.55.5.4perl5.005_04.tar.gzmaint7 years, 1 month
5.45.4.5perl5.004_05.tar.gzmaint11 years, 11 months
5.35.3.7perl5.003_07.tar.gzmaint14 years, 5 months

(A year is 365.2425 days and a month is 30.436875 days.)

HERE my @expected_releases = ( { 'file' => 'perl-5.13.11.tar.gz', 'type' => 'devel', 'release' => '5.13.11', 'age' => '14 days', 'branch' => '5.13' }, { 'file' => 'perl-5.12.3.tar.gz', 'type' => 'maint', 'release' => '5.12.3', 'age' => '2 months, 11 days', 'branch' => '5.12' }, { 'file' => 'perl-5.10.1.tar.gz', 'type' => 'maint', 'release' => '5.10.1', 'age' => '1 year, 7 months', 'branch' => '5.10' }, { 'file' => 'perl-5.8.9.tar.gz', 'type' => 'maint', 'release' => '5.8.9', 'age' => '2 years, 3 months', 'branch' => '5.8' }, { 'file' => 'perl-5.6.2.tar.gz', 'type' => 'maint', 'release' => '5.6.2', 'age' => '7 years, 4 months', 'branch' => '5.6' }, { 'file' => 'perl5.005_04.tar.gz', 'type' => 'maint', 'release' => '5.5.4', 'age' => '7 years, 1 month', 'branch' => '5.5' }, { 'file' => 'perl5.004_05.tar.gz', 'type' => 'maint', 'release' => '5.4.5', 'age' => '11 years, 11 months', 'branch' => '5.4' }, { 'file' => 'perl5.003_07.tar.gz', 'type' => 'maint', 'release' => '5.3.7', 'age' => '14 years, 5 months', 'branch' => '5.3' }, { 'file' => 'perl5.003_07.tar.gz', 'type' => 'maint', 'release' => '5.3.7', 'age' => '14 years, 5 months', 'branch' => '5.3' }, { 'file' => 'perl5.003_07.tar.gz', 'type' => 'maint', 'release' => '5.3.7', 'age' => '14 years, 5 months', 'branch' => '5.3' }, { 'file' => 'perl5.003_07.tar.gz', 'type' => 'maint', 'release' => '5.3.7', 'age' => '14 years, 5 months', 'branch' => '5.3' } ); my $app = App::perlbrew->new(); my @releases = (); for my $line ( split "\n", $html ) { $line =~ m|(.*)(.*)
.*(.*)(.*)|; push @releases, { branch => $1, release => $2, file => $3, type => $4, age => $5 } if ( $1 && $2 && $3 && $4 && $5 ); } is @releases => 11, 'found 11 releases'; is $releases[0]->{branch} => 5.13, '5.13 branch'; #is $releases[0]->{release} => 5.13, '5.13 branch'; TEST: for my $i ( 0 .. scalar @releases - 1 - 1 ) { is $releases[$i]->{branch} => $expected_releases[$i]->{branch}, "branch " . $releases[$i]->{branch} . " found"; is $releases[$i]->{release} => $expected_releases[$i]->{release}, "release " . $releases[$i]->{release} . " found"; is $releases[$i]->{file} => $expected_releases[$i]->{file}, "file " . $releases[$i]->{file} . " found"; is $releases[$i]->{type} => $expected_releases[$i]->{type}, "type " . $releases[$i]->{type} . " found"; is $releases[$i]->{age} => $expected_releases[$i]->{age}, "age " . $releases[$i]->{age} . " found"; } http-ua-detect.t000644000765000024 63313614277060 16732 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use File::Which qw(which); use App::perlbrew; use Test::More; my $expected_ua; if (which("curl")) { $expected_ua = "curl"; } elsif (which("wget")) { $expected_ua = "wget"; } elsif (which("fetch")) { $expected_ua = "fetch"; } my $detected_ua = App::perlbrew::http_user_agent_program(); is $detected_ua, $expected_ua, "UA: $detected_ua"; done_testing; command-install.t000644000765000024 462113614277060 17205 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec 0.49; # with_deep use Test::Deep; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; sub arrange_available_perls; sub arrange_command_line; sub expect_dispatch_via; describe "command install" => sub { it "should install exact perl version" => sub { arrange_command_line install => 'perl-5.12.1'; expect_dispatch_via do_install_release => [ 'perl-5.12.1', '5.12.1' ]; }; it "should install exact cperl version" => sub { arrange_command_line install => 'cperl-5.26.4'; expect_dispatch_via do_install_release => [ 'cperl-5.26.4', '5.26.4' ]; }; it "should install stable version of perl" => sub { arrange_command_line install => 'perl-stable'; arrange_available_perls qw[ perl-5.12.2 perl-5.12.3 perl-5.14.1 perl-5.14.2 perl-5.29.0 ]; expect_dispatch_via do_install_release => [ 'perl-5.14.2', '5.14.2' ]; }; it "should install blead perl" => sub { arrange_command_line install => 'perl-blead'; expect_dispatch_via do_install_blead => []; }; it "should install git checkout" => sub { my $checkout = tempdir (CLEANUP => 1); dir ($checkout, '.git')->mkpath; arrange_command_line install => $checkout; expect_dispatch_via do_install_git => [ $checkout ]; }; it "should install from archive" => sub { my $checkout = tempdir (CLEANUP => 1); my $file = file ($checkout, 'archive.tar.gz')->stringify; open my $fh, '>', $file; close $fh; arrange_command_line install => $file; expect_dispatch_via do_install_archive => [ all ( obj_isa ('App::Perlbrew::Path'), methods (stringify => $file), ) ]; }; it "should install from uri" => sub { arrange_command_line install => 'http://example.com/foo/bar'; expect_dispatch_via do_install_url => [ 'http://example.com/foo/bar' ]; }; }; runtests unless caller; sub arrange_available_perls { my (@list) = @_; App::perlbrew->stubs (available_perls => sub { $_[0]->sort_perl_versions (@list) }); } sub arrange_command_line { my (@command_line) = @_; share my %shared; $shared{app} = App::perlbrew->new (@command_line); } sub expect_dispatch_via { my ($method, $arguments) = @_; share my %shared; my $expectation = App::perlbrew->expects ($method); $expectation = $expectation->with_deep (@$arguments) if $arguments; $shared{app}->run; ok $expectation->verify; } command-install-from-archive.t000644000765000024 564313614277060 21572 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec 0.49; # with_deep use Test::Deep; use FindBin; use lib $FindBin::Bin; use App::perlbrew; use Hash::Util; require 'test_helpers.pl'; sub arrange_file; sub arrange_available_perls; sub arrange_command_line; sub expect_dispatch_via; sub should_install_from_archive; sub is_path; describe "command install " => sub { should_install_from_archive "with perl source archive" => ( filename => 'perl-5.28.0.tar.gz', dist_version => '5.28.0', installation_name => 'perl-5.28.0', ); should_install_from_archive "with perfixed perl source archive" => ( filename => 'downloaded-perl-5.28.0.tar.gz', dist_version => '5.28.0', installation_name => 'perl-5.28.0', ); should_install_from_archive "with cperl source archive" => ( filename => 'cperl-5.28.0.tar.gz', dist_version => '5.28.0', installation_name => 'cperl-5.28.0', ); should_install_from_archive "with prefixed cperl source archive" => ( filename => 'downloaded-cperl-5.28.0.tar.gz', dist_version => '5.28.0', installation_name => 'cperl-5.28.0', ); }; runtests unless caller; sub should_install_from_archive { my ($title, %params) = @_; Hash::Util::lock_keys %params, 'filename', 'dist_version', 'installation_name', ; context $title => sub { my $file; before each => sub { $file = arrange_file name => $params{filename},, tempdir => 1, ; arrange_command_line install => $file; }; expect_dispatch_via method => 'do_install_archive', with_args => [ is_path (methods (basename => $params{filename})) ]; expect_dispatch_via method => 'do_extract_tarball', stubs => { do_install_this => '' }, with_args => [ is_path (methods (basename => $params{filename})) ]; expect_dispatch_via method => 'do_install_this', stubs => { do_extract_tarball => sub { $_[-1]->dirname->child ('foo') } }, with_args => [ is_path (methods (basename => 'foo')), $params{dist_version}, $params{installation_name}, ]; }; }; sub is_path { my (@tests) = @_; all ( obj_isa ('App::Perlbrew::Path'), @tests, ); } sub arrange_file { my (%params) = @_; my $dir; $dir ||= $params{dir} if $params{dir}; $dir ||= tempdir (CLEANUP => 1) if $params{tempdir}; $dir ||= '.'; my $file = file ($dir, $params{name}); open my $fh, '>', $file; close $fh; return $file; } sub arrange_command_line { my (@command_line) = @_; share my %shared; # Enforce stringification $shared{app} = App::perlbrew->new (map "$_", @command_line); } sub expect_dispatch_via { my (%params) = @_; it "should dispatch via $params{method}()" => sub { share my %shared; App::perlbrew->stubs (%{ $params{stubs} }) if $params{stubs}; my $expectation = App::perlbrew->expects ($params{method}); $expectation = $expectation->with_deep (@{ $params{with_args} }) if $params{with_args}; $shared{app}->run; ok $expectation->verify; }; } 08.error_install_blead.t000644000765000024 117113614277060 20354 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Test::More; use Test::Exception; use App::perlbrew; { no warnings 'redefine'; sub App::perlbrew::http_download { return "ERROR" } } throws_ok( sub { my $app = App::perlbrew->new("install", "perl-blead"); $app->run; }, qr[ERROR: Failed to download https://.+/blead\.tar\.gz] ); throws_ok( sub { my $app = App::perlbrew->new("install", "blead"); $app->run; }, qr[ERROR: Failed to download https://.+/blead\.tar\.gz] ); done_testing; META.json000644000765000024 473513614277060 15122 0ustar00gugodstaff000000000000App-perlbrew-0.88{ "abstract" : "Manage perl installations in your C<$HOME>", "author" : [ "Kang-min Liu C<< >>" ], "dynamic_config" : 0, "generated_by" : "App::ModuleBuildTiny version 0.027", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "App-perlbrew", "prereqs" : { "configure" : { "requires" : { "Module::Build::Tiny" : "0.034" } }, "develop" : { "requires" : { "App::ModuleBuildTiny" : "0.027", "Pod::Markdown" : "2.002" } }, "runtime" : { "requires" : { "CPAN::Perl::Releases" : "5.20191220", "Capture::Tiny" : "0.36", "Devel::PatchPerl" : "1.80", "ExtUtils::MakeMaker" : "7.22", "File::Temp" : "0.2304", "JSON::PP" : "0", "Pod::Parser" : "1.63", "Pod::Usage" : "1.68", "local::lib" : "2.000014" } }, "test" : { "requires" : { "File::Which" : "1.21", "IO::All" : "0.51", "Path::Class" : "0.33", "Test::Exception" : "0.32", "Test::More" : "1.001002", "Test::NoWarnings" : "1.04", "Test::Output" : "1.03", "Test::Simple" : "1.001002", "Test::Spec" : "0.47", "Test::TempDir::Tiny" : "0.016" } } }, "provides" : { "App::Perlbrew::Path" : { "file" : "lib/App/Perlbrew/Path.pm" }, "App::Perlbrew::Path::Installation" : { "file" : "lib/App/Perlbrew/Path/Installation.pm" }, "App::Perlbrew::Path::Installations" : { "file" : "lib/App/Perlbrew/Path/Installations.pm" }, "App::Perlbrew::Path::Root" : { "file" : "lib/App/Perlbrew/Path/Root.pm" }, "App::Perlbrew::Util" : { "file" : "lib/App/Perlbrew/Util.pm" }, "App::perlbrew" : { "file" : "lib/App/perlbrew.pm", "version" : "0.88" } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/gugod/App-perlbrew.git", "web" : "https://github.com/gugod/App-perlbrew" } }, "version" : "0.88", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "MIT", "x_static_install" : "1" } home.t000644000765000024 335313614277060 15054 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; use Test::Deep qw[]; use Test::Spec; sub looks_like_perlbrew_home; local $App::perlbrew::PERLBREW_HOME = '/perlbrew/home'; local $ENV{PERLBREW_HOME} = '/env/home'; local $ENV{HOME} = '/home'; describe "App::perlbrew#home method" => sub { it "should return \$App::perlbrew::PERLBREW_HOME if provided" => sub { my $app = App::perlbrew->new; looks_like_perlbrew_home $app->home, '/perlbrew/home'; }; it "should default to \$ENV{PERLBREW_HOME} if provided" => sub { local $App::perlbrew::PERLBREW_HOME; my $app = App::perlbrew->new; looks_like_perlbrew_home $app->home, '/env/home'; }; it "should default to \$ENV{HOME} subpath" => sub { local $App::perlbrew::PERLBREW_HOME; local $ENV{PERLBREW_HOME}; my $app = App::perlbrew->new; looks_like_perlbrew_home $app->home, '/home/.perlbrew'; }; it "should return the instance property of 'home' if set" => sub { my $app = App::perlbrew->new; $app->home("/fnord"); looks_like_perlbrew_home $app->home, "/fnord"; }; }; runtests unless caller; sub looks_like_perlbrew_home { my ($got, $expected) = @_; my ($ok, $stack); ($ok, $stack) = Test::Deep::cmp_details "$got", "$expected"; unless ($ok) { fail; diag "Return value comparison failed"; diag Test::Deep::deep_diag $stack; return; } ($ok, $stack) = Test::Deep::cmp_details "$got", "$App::perlbrew::PERLBREW_HOME"; unless ($ok) { fail; diag "Global \$PERLBREW_HOME comparison failed"; diag Test::Deep::deep_diag $stack; return; } return Test::Deep::cmp_deeply $got, Isa ('App::Perlbrew::Path'); } command-lib.t000644000765000024 1162713614277060 16331 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use Test::Spec; use Test::Output; use Test::Exception; use App::perlbrew; require "test_helpers.pl"; mock_perlbrew_install("perl-5.14.1"); mock_perlbrew_install("perl-5.14.2"); mock_perlbrew_install("perl-5.14.3"); describe "lib command," => sub { describe "when invoked with unknown action name,", sub { it "should display error" => sub { my $x = "correcthorsebatterystaple"; my $app = App::perlbrew->new("lib", $x); stdout_like { eval { $app->run; 1; } or do { print STDERR $@; }; } qr/Unknown command: $x/; } }; describe "without lib name" => sub { it "create errs gracefully showing usage" => sub { my $app = App::perlbrew->new; throws_ok { $app->{args} = [ "lib", "create"]; $app->run; } qr/ERROR: /i; }; it "delte errs gracefully showing usage" => sub { my $app = App::perlbrew->new; throws_ok { $app->{args} = [ "lib", "delete"]; $app->run; } qr/ERROR: /i; }; }; describe "`create` sub-command," => sub { my ($app, $libdir); before each => sub { $app = App::perlbrew->new; $app->expects("current_perl")->returns("perl-5.14.2")->at_least_once; $libdir = App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita'); }; after each => sub { $libdir->rmpath; }; describe "with a bare lib name," => sub { it "creates the lib folder for current perl" => sub { stdout_is { $app->{args} = [ "lib", "create", "nobita" ]; $app->run; } qq{lib 'perl-5.14.2\@nobita' is created.\n}; ok -d $libdir; }; }; describe "with \@ in the beginning of lib name," => sub { it "creates the lib folder for current perl" => sub { stdout_is { $app->{args} = [ "lib", "create", '@nobita' ]; $app->run; } qq{lib 'perl-5.14.2\@nobita' is created.\n}; ok -d $libdir; } }; describe "with perl name and \@ as part of lib name," => sub { it "creates the lib folder for the specified perl" => sub { stdout_is { $app->{args} = [ "lib", "create", 'perl-5.14.2@nobita' ]; $app->run; } qq{lib 'perl-5.14.2\@nobita' is created.\n}; ok -d $libdir; }; it "creates the lib folder for the specified perl" => sub { stdout_is { $app->{args} = [ "lib", "create", 'perl-5.14.1@nobita' ]; $app->run; } qq{lib 'perl-5.14.1\@nobita' is created.\n}; $libdir = App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.1@nobita'); ok -d $libdir; }; it "shows errors if the specified perl does not exist." => sub { throws_ok { ## perl-5.8.8 is not mock-installed $app->{args} = [ "lib", "create", 'perl-5.8.8@nobita' ]; $app->run; } qr{^ERROR: 'perl-5.8.8' is not installed yet, 'perl-5.8.8\@nobita' cannot be created.\n}; $libdir = App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.8.8@nobita'); ok !-d $libdir; }; }; }; describe "`delete` sub-command," => sub { before each => sub { App::Perlbrew::Path ->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita') ->mkpath ; }; it "deletes the local::lib folder" => sub { stdout_is { my $app = App::perlbrew->new("lib", "delete", "nobita"); $app->expects("current_perl")->returns("perl-5.14.2")->at_least_once; $app->run; } qq{lib 'perl-5.14.2\@nobita' is deleted.\n}; ok !-d App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita'); ok !-e App::Perlbrew::Path->new ($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita'); }; it "shows errors when the given lib does not exists " => sub { throws_ok { my $app = App::perlbrew->new("lib", "delete", "yoga"); $app->expects("current_perl")->returns("perl-5.14.2")->at_least_once; $app->run; } qr{^ERROR: 'perl-5\.14\.2\@yoga' does not exist\.}; }; }; }; runtests unless caller; test.tar.gz000644000765000024 22113614277060 16014 0ustar00gugodstaff000000000000App-perlbrew-0.88/tQQ1 A en:39"6n;`墐B&x1I.ݸQ͛j=v5ޥnkt^>T#7m\4'rouM.(07.argv.t000644000765000024 76613614277060 15275 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::More; use App::perlbrew; { my $app = App::perlbrew->new("-Dcc=ccache gcc"); is $app->{D}[0], 'cc=ccache gcc'; } { my $app = App::perlbrew->new("-Dcc=ccache gcc", "-Dld=gcc"); is $app->{D}[0], 'cc=ccache gcc'; is $app->{D}[1], 'ld=gcc'; } { my $app = App::perlbrew->new("install", "-v", "perl-5.14.0", "-Dcc=ccache gcc", "-Dld=gcc"); is $app->{D}[0], 'cc=ccache gcc'; is $app->{D}[1], 'ld=gcc'; } done_testing; bashrc_content.t000644000765000024 302413614277060 17113 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use App::perlbrew; use Test::Spec; local $App::perlbrew::PERLBREW_ROOT; local %ENV; sub describe_bashrc_content; describe "App::perlbrew->BASHRC_CONTENT()" => sub { context "should not export custom PERLBREW_ROOT" => sub { describe_bashrc_content "with default settings" => ( ); describe_bashrc_content "when set only via global variable" => ( PERLBREW_ROOT => 'perlbrew/root', ); }; context "should export custom PERLBREW_ROOT" => sub { describe_bashrc_content "when env variable PERLBREW_ROOT is set" => ( ENV_PERLBREW_ROOT => 'env/root', should_match => 'env/root', ); describe_bashrc_content "when provided via argument" => ( args => [qw[ --root arg/root ]], should_match => "arg/root", ); describe_bashrc_content "when provided via argument (favor over env)" => ( args => [qw[ --root arg/root ]], ENV_PERLBREW_ROOT => 'env/root', should_match => "arg/root", ); }; }; runtests unless caller; sub describe_bashrc_content { my ($title, %params) = @_; it $title => sub { local %ENV = ( HOME => 'default/home', (PERLBREW_ROOT => $params{ENV_PERLBREW_ROOT}) x!! exists $params{ENV_PERLBREW_ROOT}, ); local $App::perlbrew::PERLBREW_ROOT = $params{PERLBREW_ROOT} || $ENV{PERLBREW_ROOT}; my $app = App::perlbrew->new (@{ $params{args} || [] }); return ok $app->BASHRC_CONTENT =~ m{^export PERLBREW_ROOT=\Q$params{should_match}\E}m if $params{should_match}; return ok $app->BASHRC_CONTENT !~ m{^export PERLBREW_ROOT=}m; }; } failure-command-install-cpanm.t000644000765000024 207113614277060 21723 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!/usr/bin/env perl use strict; use warnings; use Test::Spec; use File::Temp qw( tempdir ); use App::perlbrew; $App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 ); { no warnings 'redefine'; sub App::perlbrew::http_get { my ($url) = @_; like $url, qr/cpanm$/, "GET cpanm url: $url"; return "404 not found."; } } describe "App::perlbrew->install_cpanm" => sub { it "should no produced 'cpanm' in the bin dir, if the downloaded content seems to be invalid." => sub { my $error; my $error_produced = 0; eval { my $app = App::perlbrew->new("install-cpanm", "-q"); $app->run(); } or do { $error = $@; $error_produced = 1; }; my $cpanm = App::Perlbrew::Path->new($perlbrew_root, "bin", "cpanm"); ok $error_produced, "generated an error: $error"; ok !(-f $cpanm), "cpanm is not produced. $cpanm"; }; }; runtests unless caller; MIT-LICENSE000644000765000024 207013614277060 15670 0ustar00gugodstaff000000000000App-perlbrew-0.88/docnThe MIT License Copyright (c) 2010-2017 Kang-mil Liu Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12.sitecustomize.t000644000765000024 567413614277060 17264 0ustar00gugodstaff000000000000App-perlbrew-0.88/t#!perl use strict; use Capture::Tiny qw/capture/; use IO::All; use App::perlbrew; use File::Temp qw( tempdir ); $App::perlbrew::PERLBREW_ROOT = tempdir( CLEANUP => 1 ); $App::perlbrew::PERLBREW_HOME = tempdir( CLEANUP => 1 ); $ENV{PERLBREW_ROOT} = $App::perlbrew::PERLBREW_ROOT; use Test::More; ## setup App::Perlbrew::Path ->new ($ENV{PERLBREW_ROOT}) ->rmpath ; ## mock no warnings 'redefine'; sub App::perlbrew::do_system { my ($self, $cmd) = @_; if ($cmd =~ /sitelib/) { print "sitelib='$ENV{PERLBREW_ROOT}/perls/perl-5.14.2/lib/site_perl/5.14.2';"; return 1; } elsif ($cmd =~ /Configure/) { # pretend to succeed return 1; } else { # fail to run $? = 1<<8; $! = "Could not run '$cmd'"; return 0; } } sub App::perlbrew::do_install_release { my ($self, $dist) = @_; my ($dist_name, $dist_version) = $dist =~ m/^(.*)-([\d.]+(?:-RC\d+)?)$/; my $name = $dist; $name = $self->{as} if $self->{as}; my $root = App::Perlbrew::Path->new ($ENV{PERLBREW_ROOT}); my $installation_dir = $root->child("perls", $name); $installation_dir->mkpath; $root->child("perls", $name, "bin")->mkpath; my $perl = $root->child("perls", $name, "bin")->child("perl"); io($perl)->print("#!/bin/sh\nperl \"\$@\";\n"); chmod 0755, $perl; # fake the install $self->do_install_this("/tmp/fake-src/perl-5.14.2", $dist_version, $dist); } use warnings; ## main note "PERLBREW_ROOT set to $ENV{PERLBREW_ROOT}"; subtest "No perls yet installed" => sub { my $app = App::perlbrew->new; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 0, "no perls installed"; }; subtest "--sitecustomize option can be set" => sub { my $app = App::perlbrew->new('install', 'perl-5.14.2', '--sitecustomize=mysitecustomize.pl' ); is join(' ', $app->args), join(' ', qw(install perl-5.14.2)), "post-option args correct"; is $app->{sitecustomize}, 'mysitecustomize.pl', '--sitecustomize set as expected'; }; subtest "mock installing" => sub { my $sitefile = File::Temp->new; print $sitefile "use strict;\n"; close $sitefile; my $app = App::perlbrew->new('install', 'perl-5.14.2', "--sitecustomize=$sitefile" ); my ($output,$error) = capture { $app->run }; my @installed = grep { !$_->{is_external} } $app->installed_perls; is 0+@installed, 1, "found 1 installed perl"; is $installed[0]->{name}, "perl-5.14.2", "found expected perl"; my $root = App::Perlbrew::Path->new ($ENV{PERLBREW_ROOT}); my $perldir = $root->child("perls", "perl-5.14.2"); my $installedsite = $perldir->child('lib', 'site_perl', '5.14.2', 'sitecustomize.pl'); ok( -f $installedsite, "sitecustomize.pl installed" ); my $guts = do { local (@ARGV, $/) = $installedsite; <> }; is( $guts, "use strict;\n", "sitecustomize.pl contents correct" ); }; done_testing; # vim: ts=4 sts=4 sw=4 et: