Skip to content
Reborn.
Branch: master
Clone or download
Pull request Compare This branch is 241 commits behind tokuhirom:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin
inc/Module/Build/Pluggable
lib/App
share/plenv
t
xt
.gitattributes
.gitignore
.perl-version
.shipit
.travis.yml
Build.PL
Changes
LICENSE
MANIFEST
MANIFEST.SKIP
README.pod
carton.lock

README.pod

#!/usr/bin/perl use strict; use warnings; use utf8; use 5.008_001; use File::Spec (); use File::Basename qw/dirname basename/; use FindBin (); use lib File::Spec->catdir($FindBin::RealBin, '..', 'share', 'plenv', 'lib', 'perl5'); use File::Path qw(mkpath rmtree); my $PLENV_HOME; my $LOCAL = "@{[ File::Spec->rel2abs($FindBin::RealBin) ]}/../share/plenv/"; &main;exit; # ------------------------------------------------------------------------- sub main { my $cmd = shift @ARGV or CMD_help(); $cmd =~ s/-/_/g; my $code = __PACKAGE__->can("CMD_$cmd"); if ($code) { $code->(); } else { die "Unknown command $cmd."; } } sub home_init { if ($ENV{PLENV_HOME}) { $PLENV_HOME = $ENV{PLENV_HOME}; } elsif ($ENV{HOME}) { $PLENV_HOME = File::Spec->catdir($ENV{HOME}, ".plenv"); $ENV{PLENV_HOME} = $PLENV_HOME; } else { die "There is no ENV[PLENV_HOME] and ENV[HOME]. Please set ENV{PLENV_HOME]."; } } sub CMD_init { home_init(); print <<"..."; export PATH="$PLENV_HOME/shims:\${PATH}" ... } sub CMD_rehash { home_init(); rehash(); } sub CMD_exec { home_init(); my $bin = shift @ARGV or show_help('exec'); my ($version, $file) = detect_version(); if ($version eq 'system') { # remove shims path from ENV[PATH]. $ENV{PATH} = join( ':', grep { File::Spec->canonpath($_) ne File::Spec->canonpath("$PLENV_HOME/shims/") } File::Spec->path() ); } else { my $bindir = "$PLENV_HOME/versions/$version/bin"; unless (-x File::Spec->catfile($bindir, $bin)) { die "[plenv] There is no $bin in $bindir.(determined by @{[ $file || '-' ]})\n"; } $ENV{PATH}="$bindir:$ENV{PATH}"; } exec $bin, @ARGV; die $!; } sub CMD_which { home_init(); my $bin = shift @ARGV or show_help('which'); my ($version, $file) = detect_version(); my @path = grep { File::Spec->canonpath($_) ne File::Spec->canonpath("$PLENV_HOME/shims/") } File::Spec->path(); if ($version ne 'system') { unshift @path, "$PLENV_HOME/versions/$version/bin"; } if (my $fullpath = which($bin, @path)) { print "$fullpath\n"; exit 0; } else { print "plenv: $bin: command not found\n"; exit 1; } } sub which { my ($bin, @path) = @_; for my $dir (@path) { my $fullpath = File::Spec->catfile($dir, $bin); if (-x $fullpath) { return $fullpath; } } return undef; } sub detect_version { if ($ENV{PLENV_VERSION}) { return ($ENV{PLENV_VERSION}); } if (my $file = find_plenv_version_file()) { my $version = slurp_version($file); return ($version, $file); } return ('system'); } sub CMD_version { home_init(); my ($version, $file) = detect_version(); print "$version "; print "(set by $file)" if $file; print "\n"; } sub slurp_version { my $fname = shift; open my $fh, '<', $fname or die "$fname: $!"; my $version = do { local $/; <$fh> }; $version =~ s/\s//g; $version; } sub find_plenv_version_file { my $file = find_local_plenv_version_file(); return $file if $file; return find_global_plenv_version_file(); } sub find_local_plenv_version_file { my $dir = Cwd::getcwd(); my %seen; while (-d $dir) { return undef if $seen{$dir}++; # guard from deep recursion if (-f "$dir/.perl-version") { return "$dir/.perl-version"; } $dir = dirname($dir); } } sub find_global_plenv_version_file { if (-f "$PLENV_HOME/version") { return "$PLENV_HOME/version"; } return undef; } sub CMD_help { if (@ARGV==1) { show_help($ARGV[0]); } else { require Pod::Usage; Pod::Usage::pod2usage(-verbose => 2); } } sub show_help { my $cmd = shift; require Pod::Find; require Pod::Usage; my $input = Pod::Find::pod_where( { -inc => 1, -dirs => [ File::Spec->catdir($FindBin::RealBin, '..', 'lib') ]}, "App::plenv::$cmd" ); Carp::croak "Unknown subcommand: $input" unless $input; Pod::Usage::pod2usage( -verbose => 2, -input => $input ); } sub CMD_global { home_init(); if (my $version = shift @ARGV) { # write it write_version_file($version, "$PLENV_HOME/version"); } else { # read from global settings file my $version = do { if (my $file = find_global_plenv_version_file()) { slurp_version($file); } else { 'system' } }; print "$version\n"; } } sub CMD_local { home_init(); if (my $version = shift @ARGV) { # set it. write_version_file($version, "./.perl-version"); } else { if (my $file = find_local_plenv_version_file()) { my $version = slurp_version($file); print "$version\n"; } else { print "plenv: no local version configured for this directory\n"; } } } sub write_version_file { my ($version, $versionfile) = @_; $version =~ s/\s//g; $version =~ s/^perl-//; # remove prefix if ($version ne 'system' && !is_installed($version)) { die "$version is not installed on plenv."; } open my $fh, '>', $versionfile or die "$versionfile: $!"; print $fh $version; close $fh; } sub CMD_install { home_init(); mkpath("$PLENV_HOME/versions"); if (@ARGV == 0) { show_help('install'); exit(-1); } install(); # rehash the ~/.plenv/shims/ rehash(); return; } sub install { my $stuff = shift @ARGV; require Perl::Build; require Getopt::Long; my $installation_name; my $test; my (@D, @A, @U); Getopt::Long::Configure( 'pass_through', 'no_ignore_case', 'bundling', ); Getopt::Long::GetOptions( 'test' => \$test, 'as=s', \$installation_name, 'build-dir=s' => \my $build_dir, 'D=s@' => \@D, 'A=s@' => \@A, 'U=s@' => \@U, ); shift @ARGV if @ARGV >= 1 && $ARGV[0] eq '--'; my @configure_options = @ARGV; unless (@configure_options) { push @configure_options, '-de'; } for (@D, @A, @U) { s/^=//; } push @configure_options, map { "-D$_" } @D; push @configure_options, map { "-A$_" } @A; push @configure_options, map { "-U$_" } @U; require POSIX; my $remove_build_dir = 0; if ($build_dir) { # do not remove if user provides --build-dir parameter. $remove_build_dir = 0; # expand ~ in directory path. $build_dir =~ s!~!glob("~")!ge; } else { $remove_build_dir = 1; $build_dir = File::Spec->catdir(File::Spec->tmpdir(), POSIX::strftime("perl-build-%Y%m%d-%H%M%S$$", localtime())); } print "Creating $build_dir(building directory)\n"; mkpath($build_dir); if ($stuff =~ /\.(gz|bz2)$/) { # install from file my $dist_tarball_path = $stuff; $installation_name ||= do { my $name = basename($dist_tarball_path); $name =~ s!\.tar\..+$!!; # remove ext $name =~ s!^perl-!!; # remove prefix $name; }; if (is_installed( $installation_name )) { die "\nABORT: $installation_name is already installed.\n\n"; } # -de means "use default settings without interactive questions" my $dst_path = File::Spec->catdir($PLENV_HOME, 'versions', $installation_name); Perl::Build->install_from_tarball( $dist_tarball_path => ( build_dir => $build_dir, dst_path => $dst_path, configure_options => \@configure_options, patchperl => patchperl_cmd(), test => 0, ) ); Perl::Build->symlink_devel_executables( File::Spec->catdir($dst_path, 'bin'), ); } else { # install from CPAN my $version = $stuff; $version =~ s!^perl-!!; $installation_name ||= $version; if (is_installed( $installation_name )) { die "\nABORT: $installation_name is already installed.\n\n"; } if ($version =~ /^5\.1[13579]\./) { push @configure_options, '-Dusedevel'; } my $dst_path = File::Spec->catdir($PLENV_HOME, 'versions', $installation_name); print "Install $version to $dst_path\n"; Perl::Build->install_from_cpan( $version => ( # tarball_dir => File::Spec->catdir($PLENV_HOME, 'dists'), build_dir => $build_dir, dst_path => $dst_path, configure_options => \@configure_options, patchperl => patchperl_cmd(), test => 0, ) ); Perl::Build->symlink_devel_executables( File::Spec->catdir($dst_path, 'bin'), ); } # build dir was not useful after install successfully. # And, do not remove working directory when user specified. # Because hackers need to save object file for debugging with gdb. if ($remove_build_dir) { rmtree($build_dir); } } sub patchperl_cmd { if (-d $LOCAL) { [ $^X, "-Mlib=$LOCAL/lib/perl5/", File::Spec->catfile($LOCAL, "bin/patchperl" ) ] } else { 'patchperl' } } sub is_installed { my ($name) = @_; return grep { $name eq $_ } installed_perls(); } sub CMD_list { home_init(); my ($current, ) = detect_version(); for my $version (installed_perls(), 'system') { print $version eq $current ? "* " : " "; print "$version\n" } } sub CMD_versions { CMD_list(@_) } # alias sub installed_perls { my $self = shift; my @result; for (<$PLENV_HOME/versions/*>) { my ($name) = $_ =~ m/\/([^\/]+$)/; my $executable = File::Spec->catfile($_, 'bin', 'perl'); push @result, $name; } return @result; } sub rehash { mkpath("$PLENV_HOME/shims"); my %seen; for my $bin (map { basename($_) } grep { -x $_ } <$PLENV_HOME/versions/*/bin/*>) { next if $seen{$bin}++; my $shimbin = File::Spec->catfile($PLENV_HOME, 'shims', $bin); open my $fh, '>', $shimbin or die "$shimbin: $!"; my $cmd = do { if ($bin eq 'cpanm') { join("\n", sprintf(q{"%s" exec "$program" "$@"}, File::Spec->rel2abs($0)), sprintf(q{"%s" rehash}, File::Spec->rel2abs($0)) ) } else { sprintf(q{exec "%s" exec "$program" "$@"}, File::Spec->rel2abs($0)) } }; print $fh sprintf(<<'...', $PLENV_HOME, $cmd); #!/usr/bin/env bash set -e [ -n "$PLENV_DEBUG" ] && set -x program="${0##*/}" export PLENV_ROOT="%s" %s ... close $fh; chmod 0755, $shimbin or die "$shimbin: $!"; } } sub CMD_install_cpanm { print("Installing cpanm to current perl\n"); home_init(); my ($version, $file) = detect_version(); install_cpanm($version); } sub CMD_available { require Perl::Build; my @available = Perl::Build->available_perls(); print $_, "\n" for @available; } sub CMD_migrate_modules { home_init(); @ARGV==2 or show_help('migrate-modules'); my ($src, $dst) = @ARGV; my $srcperl = "${PLENV_HOME}/versions/${src}/bin/perl"; my $dstcpanm = "${PLENV_HOME}/versions/${dst}/bin/cpanm"; install_cpanm($dst); open my $srcfh, "-|", $srcperl, '-MExtUtils::Installed', '-e', 'print $_, "\n" for ExtUtils::Installed->new->modules' or die "Cannot exec: $!"; open my $dstfh, "|-", $dstcpanm or die "Cannot exec $dstcpanm: $!"; while (<$srcfh>) { print $dstfh $_; } close $srcfh; close $dstfh; } sub install_cpanm { my ($version) = @_; my $perl = "${PLENV_HOME}/versions/${version}/bin/perl"; my $cpanm = _find_cpanm_path(); system("$perl $cpanm App::cpanminus") == 0 or die "Cannot install cpanm to $perl"; } sub _find_cpanm_path { { my $cpanm = File::Spec->catfile($FindBin::RealBin, '..', 'share/plenv/bin/cpanm'); return $cpanm if -f $cpanm; } { my $cpanm = $^X; $cpanm =~ s!/perl([0-9\.]*)$!/cpanm!; return $cpanm if -f $cpanm; } die "[ABORT] Cannot find bundled `cpanm` command\n"; } __END__ =encoding utf8 =head1 NAME plenv - perl binary manager =head1 SYNOPSIS plenv help # list available perl versions plenv available # install perl5 binary plenv install 5.16.2 -Dusethreads # execute command on current perl plenv exec ack # change global default perl to 5.16.2 plenv global 5.16.2 # change local perl to 5.14.0 plenv local 5.14.0 # run this command after install cpan module, contains executable script. plenv rehash # install cpanm to current perl plenv install-cpanm # migrate modules(install all installed modules for 5.8.9 to 5.16.2 environment.) plenv migrate-modules 5.8.9 5.16.2 # locate a program file in the plenv's path plenv which cpanm =head1 DESCRIPTION Use plenv to pick a Perl version for your application and guarantee that your development environment matches production. Put plenv to work with [Carton](http://github.com/miyagawa/carton/) for painless Perl upgrades and bulletproof deployments. =head1 plenv vs. perlbrew plenv supports project local version determination. i.e. .perl-version file support. =head1 INSTALLATION =head2 INSTALL FROM CPAN Install plenv with CPAN. $ sudo -H cpan -i App::plenv =head2 INSTALL FROM Homebrew You can use homebrew to install plenv. $ brew install plenv =head2 INSTALL WITH GIT 1. Check out plenv into ~/.plenv/ $ git clone git://github.com/tokuhirom/plenv.git ~/.plenv 2. Add ~/.plenv/bin/ to your $PATH for access to the `plenv` command-line utility. $ echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.bash_profile **Ubuntu note**: Modify your `~/.profile` instead of `~/.bash_profile`. **Zsh note**: Modify your `~/.zshrc` file instead of `~/.bash_profile`. =head1 SETUP SHELL SETTINGS =over 4 =item Add `plenv init` to your shell to enable shims and autocompletion. $ echo 'eval "$(plenv init -)"' >> ~/.bash_profile I =item Restart your shell as a login shell so the path changes take effect. You can now begin using plenv. $ exec $SHELL -l =back =head1 Perl version detection plenv detects current perl version with following order. =over 4 =item PLENV_VERSION environment variable =item .perl-version file in current and upper directories. =item global settings(~/.plenv/version) =item use system perl =back =head1 DEPENDENCIES * Perl 5.8.1+ * wget or curl or fetch. =head1 FAQ =over 4 =item How can I install cpanm? Try to use following command. % plenv install-cpanm This command install cpanm to current environment. =item What should I do for installing the module which I used for new Perl until now? You can use C< migrate-modules > subcommand. % plenv migrate-modules 5.8.2 5.16.2 It make a list of installed modules in 5.8.2, and install these modules to 5.16.2 environment. =item How can I enable -g option without slowing down binary? Use following command. % plenv install 5.16.2 -DDEBUGGING=-g =back =head1 BUG REPORTING Plese use github issues: L. =head1 AUTHOR Tokuhiro Matsuno Etokuhirom AAJKLFJEF@ GMAIL COME =head1 SEE ALSO L provides same feature. But plenv provides project local file: B< .perl-version >. Most of part was inspired from L. =head1 LICENSE Copyright (C) Tokuhiro Matsuno This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut
You can’t perform that action at this time.