App-perlbrew-0.66/000755 000765 000024 00000000000 12177031266 014262 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/bin/000755 000765 000024 00000000000 12177031266 015032 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/Changes000644 000765 000024 00000035111 12177031140 015545 0ustar00gugodstaff000000 000000 0.66: # 2013-08-03T00:22:29+0200 - fix a bug the made download failed with curl program. 0.65: # 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: # 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: # 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: # 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: # 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: # 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: # 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: # 2012-11-13T19:57:03+0100 - Fix an infinite re-exec loop 0.56: # 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: # 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: # 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: # 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: # 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: # 2012-09-01T11:25:41+0200 - properly remove perlbrew-related PERL5LIB entries. GH #197 - minor documentation tweak. 0.49: # 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: # 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: # 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. App-perlbrew-0.66/doc/000755 000765 000024 00000000000 12177031266 015027 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/inc/000755 000765 000024 00000000000 12177031266 015033 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/lib/000755 000765 000024 00000000000 12177031266 015030 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/LICENSE000644 000765 000024 00000002101 12176370331 015257 0ustar00gugodstaff000000 000000 The MIT License Copyright (c) 2010,2011,2012,2013 Kang-min 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. App-perlbrew-0.66/Makefile.PL000644 000765 000024 00000001310 12176370331 016225 0ustar00gugodstaff000000 000000 use inc::Module::Install; license 'mit'; all_from 'lib/App/perlbrew.pm'; repository 'git://github.com/gugod/App-perlbrew.git'; requires 'Devel::PatchPerl' => '1.00', 'local::lib' => '1.008009', 'Capture::Tiny' => '0.22', 'CPAN::Perl::Releases' => '1.26'; test_requires 'Test::Simple' => '0.98', 'Test::More' => '0', 'Test::Output' => '0.04', # stdout_like added in 0.04 'Test::Exception' => '0', 'Test::NoWarnings' => '0', 'Test::Spec' => '0.46', # with() added in 0.46 'Path::Class' => '0', 'IO::All' => '0.46', 'File::Temp' => '0'; install_script 'bin/perlbrew'; tests 't/*.t'; WriteAll; App-perlbrew-0.66/MANIFEST000644 000765 000024 00000002545 12176370151 015417 0ustar00gugodstaff000000 000000 bin/perlbrew Changes doc/MIT-LICENSE doc/notes.org doc/PERL-LICENSE inc/Module/Install.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Scripts.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm lib/App/perlbrew.pm LICENSE Makefile.PL MANIFEST This list of files META.yml README t/00.load.t t/01.options.t t/02.format_perl_version.t t/03.path_with_tilde.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/08.error_mirror.t t/09.exit_status.t t/10.resolve.t t/11.editdist.t t/11.root_from_arg.t t/12.sitecustomize.t t/13.perl_release.t t/14.perl_version_parsing.t t/15.no-reuse-build-dir.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-patchperl.t t/command-lib.t t/command-list.t t/current_perl.t t/do_system.t t/failure-command-install-cpanm.t t/failure-command-install-patchperl.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 App-perlbrew-0.66/META.yml000644 000765 000024 00000001614 12177031266 015535 0ustar00gugodstaff000000 000000 --- abstract: 'Manage perl installations in your $HOME' author: - 'Kang-min Liu C<< >>' build_requires: ExtUtils::MakeMaker: 6.59 File::Temp: 0 IO::All: 0.46 Path::Class: 0 Test::Exception: 0 Test::More: 0 Test::NoWarnings: 0 Test::Output: 0.04 Test::Simple: 0.98 Test::Spec: 0.46 configure_requires: ExtUtils::MakeMaker: 6.59 distribution_type: module dynamic_config: 1 generated_by: 'Module::Install version 1.06' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 module_name: App::perlbrew name: App-perlbrew no_index: directory: - inc - t requires: CPAN::Perl::Releases: 1.26 Capture::Tiny: 0.22 Devel::PatchPerl: 1.00 local::lib: 1.008009 perl: 5.8.0 resources: license: http://opensource.org/licenses/mit-license.php repository: git://github.com/gugod/App-perlbrew.git version: 0.66 App-perlbrew-0.66/README000644 000765 000024 00000017065 12121426432 015143 0ustar00gugodstaff000000 000000 Name: App::perlbrew - Manage perl installations in your $HOME Description: perlbrew is a program to automate the building and installation of perl in an easy way. It installs everything to "~/perl5/perlbrew", and requires you to tweak your PATH by including a bashrc/cshrc file it provides. You then can benefit from not having to run 'sudo' commands to install cpan modules because those are installed inside your HOME too. It provides multiple isolated perl environments, and a mechanism for you to switch between them. For the documentation of perlbrew usage see perlbrew command on CPAN, or by running "perlbrew help". 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 -kL http://install.perlbrew.pl | bash Or this one, if you have "fetch" (default on FreeBSD): fetch -o- http://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 minimun system perl version requirement is 5.8.0, which should be good enough for most of the OSes these days. A packed version of "patchperl" 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 -kL http://install.perlbrew.pl | bash 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. Configuration: PERLBREW_ROOT By default, perlbrew builds and installs perls into "$ENV{HOME}/perl5/perlbrew" directory. To use a different directory, set this environment variable in your "bashrc" to the directory in your shell RC before sourcing perlbrew's RC. It is possible to share one perlbrew root with multilpe user account on the same machine. Therefore people do not have to install the same version of perl over an over. Let's say "/opt/perl5" 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, everone's PATH should include "/opt/perl5/bin" and "/opt/perl5/perls/${PERLBREW_PERL}/bin". Each user can invoke "perlbrew switch" and "perlbrew use" to independently switch to different perl environment of their choice. However, only the user with write permission to $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 "lib" command to construct a personal local::lib environment. local::lib environments are personal, and are not shared between different users. For more detail, read "perlbrew help lib" and the documentation of local::lib. If you want even a cooler module isolation and wish to install CPAN modules used for just one project, you should use carton 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 -kL http://install.perlbrew.pl | bash After doing this, the perlbrew executable is installed as "/opt/perl5/bin/perlbrew" PERLBREW_HOME By default, perlbrew stores per-user setting to "$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 "PERLBREW_HOME" environment variable to tell perlbrew where to look for the initialization file. Here's a brief bash snippet for the given senario. 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 Project Development: perlbrew project uses github and RT for issue tracking. Issues sent to these two systems will eventually be reviewed and handled. See for a list of project contributors. Author: Kang-min Liu "" Copyright: Copyright (c) 2010, 2011, 2012 Kang-min Liu "". 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. App-perlbrew-0.66/t/000755 000765 000024 00000000000 12177031266 014525 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/t/00.load.t000644 000765 000024 00000000150 11534745500 016042 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use Test::More tests => 1; use lib qw(lib); use_ok('App::perlbrew'); App-perlbrew-0.66/t/01.options.t000644 000765 000024 00000002046 11645601725 016630 0ustar00gugodstaff000000 000000 #!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'; App-perlbrew-0.66/t/02.format_perl_version.t000644 000765 000024 00000001313 12110142770 021175 0ustar00gugodstaff000000 000000 #!/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}" ); } } App-perlbrew-0.66/t/03.path_with_tilde.t000644 000765 000024 00000000513 11620365516 020302 0ustar00gugodstaff000000 000000 #!perl use strict; use Test::More tests => 2; use App::perlbrew; my $app = App::perlbrew->new(); my $home = $app->env("HOME"); SKIP: { skip "This test is meanless when \$HOME-less.", 2 unless $home; is $app->path_with_tilde("$home/foo/bar"), "~/foo/bar"; is $app->path_with_tilde("/baz/foo/bar"), "/baz/foo/bar"; } App-perlbrew-0.66/t/03.test_get_available_versions.t000644 000765 000024 00000032225 11646164204 022704 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::More; use App::perlbrew; { no warnings 'redefine'; my $html; sub App::perlbrew::http_get { return $html if $html; local $/ = undef; $html = ; } } plan tests => 9; my $app = App::perlbrew->new(); is scalar $app->available_perls(), 8, "Correct number of releases found"; my @known_perl_versions = ( 'perl-5.13.11', 'perl-5.12.3', '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"; } __DATA__ 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.gz
5.12 5.12.3 Maint 2011-01-22 perl-5.12.3.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.

App-perlbrew-0.66/t/04.find_available_perls.t000644 000765 000024 00000011316 11561421547 021264 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::More; use Data::Dumper; 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"; } App-perlbrew-0.66/t/05.get_current_perl.t000644 000765 000024 00000002313 12152574055 020500 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/06.installed_perls.t000644 000765 000024 00000001043 11617775242 020327 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/07.argv.t000644 000765 000024 00000000766 11617775242 016116 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/08.error_available.t000644 000765 000024 00000000535 11617775242 020303 0ustar00gugodstaff000000 000000 #!/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-0.66/t/08.error_install.t000644 000765 000024 00000001433 12177031133 020011 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use lib qw(lib); use Test::More; use Test::Exception; use Path::Class; 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::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("perls") ); App::perlbrew::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("build") ); App::perlbrew::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("dists") ); 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; App-perlbrew-0.66/t/08.error_install_blead.t000644 000765 000024 00000001176 12177031133 021144 0ustar00gugodstaff000000 000000 #!/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; 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 perl-blead tarball.] ); throws_ok( sub { my $app = App::perlbrew->new("install", "blead"); $app->run; }, qr[ERROR: Failed to download perl-blead tarball.] ); done_testing; App-perlbrew-0.66/t/08.error_install_cpanm.t000644 000765 000024 00000000620 11760425411 021167 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/08.error_mirror.t000644 000765 000024 00000000530 11654562567 017675 0ustar00gugodstaff000000 000000 #!/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("mirror"); $app->run; }, qr"ERROR: Failed to retrieve the mirror list." ); done_testing; App-perlbrew-0.66/t/09.exit_status.t000644 000765 000024 00000001072 11760425411 017511 0ustar00gugodstaff000000 000000 #!/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__)->dir->parent->subdir("bin")->file("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; App-perlbrew-0.66/t/10.resolve.t000644 000765 000024 00000004047 11711163042 016604 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/11.editdist.t000644 000765 000024 00000000500 11654562567 016752 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::More; use App::perlbrew; *ed = *App::perlbrew::editdist; is ed(qw/Joe Jim/), 2; is ed(qw/Jack Jill/), 3; is ed(qw/Jim Jimmy/), 2; is ed(qw/superman supergirl/), 4; is ed(qw/supercalifragilisticexpyalligocious superman/), 29; is ed(qw/foo bar/), 3; done_testing; App-perlbrew-0.66/t/11.root_from_arg.t000644 000765 000024 00000001661 11654562567 020011 0ustar00gugodstaff000000 000000 #!/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::Spec; use Test::Exception; describe "App::perlbrew#root method" => sub { it "should returns \$App::perlbrew::PERLBREW_ROOT normally" => sub { my $app = App::perlbrew->new; is $app->root, $App::perlbrew::PERLBREW_ROOT; }; it "should returns the instance property of 'root' if set" => sub { my $app = App::perlbrew->new; $app->root("/fnord"); is $app->root, "/fnord"; }; }; describe "App::perlbrew->new" => sub { it "accept --root args and treat it as the value od PERLBREW_ROOT for the instance" => sub { my $temp_perlbrew_root = tempdir( CLEANUP => 1); my $app = App::perlbrew->new("--root" => $temp_perlbrew_root); is $app->root, $temp_perlbrew_root; }; }; runtests unless caller; App-perlbrew-0.66/t/12.sitecustomize.t000644 000765 000024 00000005661 11760425411 020046 0ustar00gugodstaff000000 000000 #!perl use strict; use Path::Class; 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::rmpath( $ENV{PERLBREW_ROOT} ); ## 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 = dir($ENV{PERLBREW_ROOT}); my $installation_dir = $root->subdir("perls", $name); App::perlbrew::mkpath($installation_dir); App::perlbrew::mkpath($root->subdir("perls", $name, "bin")); my $perl = $root->subdir("perls", $name, "bin")->file("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 = dir($ENV{PERLBREW_ROOT}); my $perldir = $root->subdir("perls", "perl-5.14.2"); my $installedsite = $perldir->file('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: App-perlbrew-0.66/t/13.perl_release.t000644 000765 000024 00000002720 12121426432 017567 0ustar00gugodstaff000000 000000 #!/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::Spec; use Test::Exception; use CPAN::Perl::Releases; 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.003_07 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 qq{Download}; }; *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?://search\.cpan\.org/CPAN/authors/id/SOMEONE/${ball}$#, $url; *CPAN::Perl::Releases::perl_tarballs = $orig_sub; }; }; runtests unless caller; App-perlbrew-0.66/t/14.perl_version_parsing.t000644 000765 000024 00000007060 12045457031 021366 0ustar00gugodstaff000000 000000 #!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; plan tests => 0+@versions; my @versions_i = sort { $a->[0] <=> $b->[0] } map { [App::perlbrew::perl_version_to_integer($_), $_] } @versions; for my $i (0..$#versions) { is $versions[$i], $versions_i[$i]->[1]; } App-perlbrew-0.66/t/15.no-reuse-build-dir.t000644 000765 000024 00000001532 12152574055 020546 0ustar00gugodstaff000000 000000 use strict; use warnings; use Test::More tests => 6; use File::Spec; use File::Basename qw(basename); use File::Path qw(mkpath); 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 = File::Spec->catdir($pb->root, qw/build test/); my $test_file = File::Spec->catfile( $test_dir, 3 ); mkpath( $test_dir ); 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( File::Spec->catfile($FindBin::Bin, 'test.tar.gz') ); is basename( $extracted_dir ) => 'test', 'Test tarball extracted as expected'; ok !-e $test_file, 'Test file 3 was unlinked by tar'; ok -e File::Spec->catfile( $test_dir, $_ ), "Test file $_ exists" for 1..2; App-perlbrew-0.66/t/command-alias.t000644 000765 000024 00000002200 12130240450 017373 0ustar00gugodstaff000000 000000 #!/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 File::Temp qw( tempdir ); use File::Spec::Functions qw( catdir ); 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; App-perlbrew-0.66/t/command-available.t000644 000765 000024 00000002676 11646164204 020260 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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 ); describe "available command output, when nothing installed locally," => sub { it "should display a list of perl versions" => sub { my $app = App::perlbrew->new("available"); my @available_perls = qw(perl-5.14.1 perl-5.14.2 perl-5.12.4); $app->expects("available_perls")->returns(@available_perls); stdout_is sub { $app->run(); }, < sub { it "should display a list of perl versions, with markers on installed versions" => sub { my $app = App::perlbrew->new("available"); my @available_perls = qw(perl-5.14.1 perl-5.14.2 perl-5.12.4); my @installed_perls = ( { name => "perl-5.14.1" }, { name => "perl-5.14.2" } ); $app->expects("available_perls")->returns(@available_perls); $app->expects("installed_perls")->returns(@installed_perls); stdout_is sub { $app->run(); }, < 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; App-perlbrew-0.66/t/command-display-rc.t000644 000765 000024 00000001235 11645601725 020400 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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; App-perlbrew-0.66/t/command-env.t000644 000765 000024 00000004560 12122132127 017107 0ustar00gugodstaff000000 000000 #!/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 File::Temp qw( tempdir ); use File::Spec::Functions qw( catdir ); 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}; }; 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 } } }; runtests unless caller; App-perlbrew-0.66/t/command-exec.t000644 000765 000024 00000024514 12176370331 017256 0ustar00gugodstaff000000 000000 #!/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, file($App::perlbrew::PERLBREW_ROOT, "bin"); is $perlbrew_perl_bin_path, file($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, file($App::perlbrew::PERLBREW_ROOT, "bin"); is $perlbrew_perl_bin_path, file($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, [ file($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), file($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.12.3", "bin"), file($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, [ file($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, [ file($App::perlbrew::PERLBREW_ROOT, "perls", "perl-5.14.1", "bin"), file($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 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->current_perl_executable, 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"; }; }; }; runtests unless caller; App-perlbrew-0.66/t/command-help.t000644 000765 000024 00000001114 11760425411 017247 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require "test_helpers.pl"; mock_perlbrew_install("perl-5.12.3"); use Test::Spec; use Test::Output qw(stdout_is stdout_from stdout_like); my $bin_perlbrew = file(__FILE__)->dir->parent->subdir("bin")->file("perlbrew"); describe "help" => sub { it "should instruct user to read help for individual commands." => sub { my $perl = $^X; my $out = `$perl -Ilib $bin_perlbrew help`; like $out, qr/perlbrew help /si; }; }; runtests unless caller; App-perlbrew-0.66/t/command-info.t000644 000765 000024 00000004754 12177031133 017264 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Test::Output; 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("current_perl_executable")->returns($perl_path)->at_least_once(); # actaully real perl path $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("current_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/; }; }; runtests unless caller; App-perlbrew-0.66/t/command-install-cpanm.t000644 000765 000024 00000001614 12152574055 021073 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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 = file($perlbrew_root, "bin", "cpanm")->absolute; ok -f $cpanm, "cpanm is produced. $cpanm"; ok -x $cpanm, "cpanm should be an executable."; }; }; runtests unless caller; App-perlbrew-0.66/t/command-install-patchperl.t000644 000765 000024 00000001700 12152574055 021753 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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 = file($perlbrew_root, "bin", "patchperl")->absolute; ok -f $patchperl, "patchperl is produced. $patchperl"; ok -x $patchperl, "patchperl should be an executable."; }; }; runtests unless caller; App-perlbrew-0.66/t/command-lib.t000644 000765 000024 00000011112 12042041115 017051 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use File::Spec::Functions qw( catdir ); 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 { it "shows a page of usage synopsis when no sub-command are given." => sub { stdout_like { App::perlbrew->new("lib")->run; } qr/usage/i; }; 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 = dir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita'); }; after each => sub { $libdir->rmtree; }; 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 = dir($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 = dir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.8.8@nobita'); ok !-d $libdir; }; }; }; describe "`delete` sub-command," => sub { before each => sub { App::perlbrew::mkpath( catdir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita') ); }; 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 catdir($App::perlbrew::PERLBREW_HOME, "libs", 'perl-5.14.2@nobita'); ok !-e catdir($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; App-perlbrew-0.66/t/command-list.t000644 000765 000024 00000004670 12042041115 017271 0ustar00gugodstaff000000 000000 #!/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::Temp qw( tempdir ); use File::Spec::Functions qw( catdir ); use Test::Spec; use Test::Output qw(stdout_is stdout_from); 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"); my $out = stdout_from { $app->run; }; ## Remove paths to system perl from the list $out =~ s/^[* ] \/.+$//mg; $out =~ s/\n\n+/\n/; is $out, <<"EOF"; * perl-5.12.3 perl-5.12.4 perl-5.14.1 perl-5.14.2 EOF }; }; 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"); my $out = stdout_from { $app->run }; ## Remove paths to system perl from the list $out =~ s/^[* ] \/.+$//mg; $out =~ s/\n\n+/\n/; is $out, <<'OUT'; * perl-5.12.3 perl-5.12.3@nobita perl-5.12.3@shizuka perl-5.12.4 perl-5.14.1 perl-5.14.2 OUT }; it "marks currently activated lib", sub { $ENV{PERLBREW_LIB} = "nobita"; my $app = App::perlbrew->new("list"); my $out = stdout_from { $app->run }; ## Remove paths to system perl from the list $out =~ s/^[* ] \/.+$//mg; $out =~ s/\n\n+/\n/; is $out, <<'OUT'; perl-5.12.3 * perl-5.12.3@nobita perl-5.12.3@shizuka perl-5.12.4 perl-5.14.1 perl-5.14.2 OUT }; }; }; runtests unless caller; App-perlbrew-0.66/t/current_perl.t000644 000765 000024 00000002501 11760425411 017410 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/do_system.t000644 000765 000024 00000001046 11760425411 016715 0ustar00gugodstaff000000 000000 #!/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()'; App-perlbrew-0.66/t/failure-command-install-cpanm.t000644 000765 000024 00000002115 12152574055 022515 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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 = file($perlbrew_root, "bin", "cpanm")->absolute; ok $error_produced, "generated an error: $error"; ok !(-f $cpanm), "cpanm is not produced. $cpanm"; }; }; runtests unless caller; App-perlbrew-0.66/t/failure-command-install-patchperl.t000644 000765 000024 00000002213 12152574055 023400 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Test::Spec; use Path::Class; use IO::All; 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-0.66/t/http.t000644 000765 000024 00000003415 12177031133 015665 0ustar00gugodstaff000000 000000 #!/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( "http://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; App-perlbrew-0.66/t/installation-perlbrew.t000644 000765 000024 00000001712 11760425411 021230 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; require 'test_helpers.pl'; use Path::Class; use Test::More; 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"); }; done_testing; App-perlbrew-0.66/t/installation.t000644 000765 000024 00000002725 11760425411 017415 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/installation2.t000644 000765 000024 00000002730 12177031133 017470 0ustar00gugodstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; use App::perlbrew; 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("/a/fake/path/to/perl-5.12.3"); my $e2 = $app->expects("do_install_this")->returns(""); $app->do_install_archive("/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; } }; }; runtests unless caller; App-perlbrew-0.66/t/installation3.t000755 000765 000024 00000001627 12110147714 017500 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/t/test.tar.gz000644 000765 000024 00000000221 12152574055 016627 0ustar00gugodstaff000000 000000 ‹QŸ‘QíÑ1 A …áen°É:39Å"6n¼¿;Š`å¢Bø¿&x±¬1I.ݸ·QÍ›¾×±Ùj=Œv5­Þ¥´ä¿nk¯¥Èåt^>ííÍÿTŒüçÜ#àÞë7ù·m\4÷­'òÉroü’uòöÜÊM.(App-perlbrew-0.66/t/test_helpers.pl000644 000765 000024 00000003555 12152574055 017574 0ustar00gugodstaff000000 000000 =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 Test::More; use Path::Class; use IO::All; 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; App::perlbrew::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("perls") ); App::perlbrew::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("build") ); App::perlbrew::mkpath( dir($ENV{PERLBREW_ROOT})->subdir("dists") ); no warnings 'redefine'; sub App::perlbrew::do_install_release { my ($self, $name) = @_; $name = $self->{as} if $self->{as}; my $root = dir($App::perlbrew::PERLBREW_ROOT); my $installation_dir = $root->subdir("perls", $name); $self->{installation_name} = $name; App::perlbrew::mkpath($installation_dir); App::perlbrew::mkpath($root->subdir("perls", $name, "bin")); my $perl = $root->subdir("perls", $name, "bin")->file("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::mkpath(dir($App::perlbrew::PERLBREW_HOME, "libs", $name)); } 1; App-perlbrew-0.66/t/unit-files-are-the-same.t000644 000765 000024 00000000756 12176370331 021245 0ustar00gugodstaff000000 000000 #!/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; App-perlbrew-0.66/lib/App/000755 000765 000024 00000000000 12177031266 015550 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/lib/App/perlbrew.pm000644 000765 000024 00000234746 12177031140 017737 0ustar00gugodstaff000000 000000 package App::perlbrew; use strict; use warnings; use 5.008; our $VERSION = "0.66"; 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 List::Util qw/min/; use Getopt::Long (); ### global variables local $SIG{__DIE__} = sub { my $message = shift; warn $message; exit(1); }; our $CONFIG; our $PERLBREW_ROOT = $ENV{PERLBREW_ROOT} || joinpath($ENV{HOME}, "perl5", "perlbrew"); our $PERLBREW_HOME = $ENV{PERLBREW_HOME} || joinpath($ENV{HOME}, ".perlbrew"); 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 joinpath { join "/", @_ } sub mkpath { require File::Path; File::Path::mkpath([@_], 0, 0777); } sub rmpath { require File::Path; File::Path::rmtree([@_], 0, 0); } 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}' }, wget => { test => '--version >/dev/null 2>&1', get => '--quiet -O - {url}', download => '--quiet -O {output} {url}', }, fetch => { test => '--version >/dev/null 2>&1', get => '-o - {url}', download => '{url}' } ); sub http_user_agent_program { my $program; for my $p (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"; } return $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 $download_command = http_user_agent_command( download => { url => $url, output => $path } ); my $status = system($download_command); unless ($status == 0) { 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() for '$command': $!"; local $/; my $body = <$fh>; close $fh; die 'Page not retrieved; HTTP error code 400 or above.' if $program eq 'curl' # Exit code is 22 on 404s etc and $? >> 8 == 22; # exit code is packed into $?; see perlvar die 'Page not retrieved: fetch failed.' if $program eq 'fetch' # Exit code is not 0 on error and $?; die 'Server issued an error response.' if $program eq 'wget' # Exit code is 8 on 404s etc and $? >> 8 == 8; 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]; } # 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]; } ### methods sub new { my($class, @argv) = @_; my %opt = ( original_argv => \@argv, force => 0, quiet => 0, D => [], U => [], A => [], sitecustomize => '', noman => '', variation => '', both => [], append => '', ); $opt{$_} = '' for keys %flavor; # 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/^=//; } } return bless \%opt, $class; } sub parse_cmdline { my ($self, $params, @ext) = @_; my @f = map { $flavor{$_}{opt} || $_ } keys %flavor; Getopt::Long::GetOptions( $params, 'force|f!', 'notest|n!', 'quiet|q!', 'verbose|v', 'as=s', 'append=s', 'help|h', 'version', 'root=s', 'switch', 'all', # options passed directly to Configure 'D=s@', 'U=s@', 'A=s@', 'j=i', # options that affect Configure and customize post-build 'sitecustomize=s', 'noman', # flavors support 'both|b=s@', 'all-variations', 'common-variations', @f, @ext ) or run_command_help(1); } sub root { my ($self, $new_root) = @_; if (defined($new_root)) { $self->{root} = $new_root; } return $self->{root} || $PERLBREW_ROOT; } 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_perl_executable { my ($self) = @_; return $self->installed_perl_executable($self->current_perl); } 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 = joinpath($self->root, "perls", $name, "bin", "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, $v) = @_; 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 path_with_tilde { my ($self, $dir) = @_; my $home = $self->env('HOME'); $dir =~ s/^\Q$home\E/~/ if $home; return $dir; } sub is_shell_csh { my ($self) = @_; return 1 if $self->env('SHELL') =~ /(t?csh)/; return 0; } sub run { my($self) = @_; $self->run_command($self->args); } sub args { my ( $self ) = @_; 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(defined *$glob{CODE}) { $sym =~ s/^run_command_//; $sym =~ s/_/-/g; push @commands, $sym; } } } return @commands; } sub find_similar_commands { my ( $self, $command ) = @_; my $SIMILAR_DISTANCE = 6; my @commands = sort { $a->[1] <=> $b->[1] } grep { defined } map { my $d = editdist($_, $command); ($d < $SIMILAR_DISTANCE) ? [ $_, $d ] : undef } $self->commands; if(@commands) { my $best = $commands[0][1]; @commands = map { $_->[0] } grep { $_->[1] == $best } @commands; } return @commands; } 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"; } sub run_command_help { my ($self, $status, $verbose) = @_; 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"; } 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 _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"; } } sub run_command_available { my ( $self, $dist, $opts ) = @_; my @available = $self->available_perls(@_); my @installed = $self->installed_perls(@_); my $is_installed; for my $available (@available) { $is_installed = 0; for my $installed (@installed) { my $name = $installed->{name}; my $cur = $installed->{is_current}; if ( $available eq $installed->{name} ) { $is_installed = 1; last; } } print $is_installed ? 'i ' : ' ', $available, "\n"; } } sub available_perls { my ( $self, $dist, $opts ) = @_; my $url = $self->{all} ? "http://www.cpan.org/src/5.0/" : "http://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"; } my @available_versions; for ( split "\n", $html ) { if ( $self->{all} ) { push @available_versions, $1 if m|(.+?)|; } else { push @available_versions, $1 if m|(.+?)|; } } s/\.tar\.gz// for @available_versions; return @available_versions; } sub perl_release { my ($self, $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 = $self->cpan_mirror() . "/src/5.0/$dist_tarball"; return ( $dist_tarball, $dist_tarball_url ) if ( $index =~ /href\s*=\s*"\Q$dist_tarball\E"/ms ); } } } # try CPAN::Perl::Releases require 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 = $self->cpan_mirror() . "/authors/id/$x"; return ($dist_tarball, $dist_tarball_url); } # try to find it on search.cpan.org my $mirror = $self->config->{mirror}; my $header = $mirror ? { 'Cookie' => "cpan=$mirror->{url}" } : undef; my $html = http_get("http://search.cpan.org/dist/perl-${version}", $header); unless ($html) { die "ERROR: Failed to locate perl-${version} tarball."; } my ($dist_path, $dist_tarball) = $html =~ m[Download]; die "ERROR: Cannot find the tarball for perl-$version\n" if !$dist_path and !$dist_tarball; my $dist_tarball_url = "http://search.cpan.org${dist_path}"; return ($dist_tarball, $dist_tarball_url); } sub run_command_init { my $self = shift; my @args = @_; if (@args && $args[0] eq '-') { if ($self->is_shell_csh) { } else { $self->run_command_init_in_bash; } exit 0; } mkpath($_) for (grep { ! -d $_ } map { joinpath($self->root, $_) } qw(perls dists build etc bin)); my ($f, $fh) = @_; my $etc_dir = joinpath($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"], ) { my ($file_name, $method) = @$_; my $path = joinpath($etc_dir, $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 ( $shrc, $yourshrc ); if ( $self->is_shell_csh) { $shrc = 'cshrc'; $self->env("SHELL") =~ m/(t?csh)/; $yourshrc = $1 . "rc"; } elsif ($self->env("SHELL") =~ m/zsh\d?$/) { $shrc = "bashrc"; $yourshrc = 'zshenv'; } else { $shrc = "bashrc"; $yourshrc = "bash_profile"; } my $root_dir = $self->path_with_tilde($self->root); my $pb_home_dir = $self->path_with_tilde($PERLBREW_HOME); my $code = qq( source $root_dir/etc/${shrc}); if ($PERLBREW_HOME ne joinpath($ENV{HOME}, ".perlbrew")) { $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; } mkpath( joinpath($self->root, "bin" )); 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 = $self->path_with_tilde($target); print "perlbrew is installed: $path\n" unless $self->{quiet}; $self->run_command_init(); return; } sub do_install_git { my $self = shift; my $dist = shift; 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($dist_extracted_dir, $dist_version, "$dist_name-$dist_version"); return; } sub do_install_url { my $self = shift; my $dist = shift; 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{/([^/]*)$}; my $dist_tarball_path = joinpath($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" 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 = shift; my $dist_tarball = shift; # Assuming the dir extracted from the tarball is named after the tarball. my $dist_tarball_basename = $dist_tarball; $dist_tarball_basename =~ s{.*/([^/]+)\.tar\.(?:gz|bz2)$}{$1}; # Note that this is incorrect for blead. my $extracted_dir = "@{[ $self->root ]}/build/$dist_tarball_basename"; # Was broken on Solaris, where GNU tar is probably # installed as 'gtar' - RT #61042 my $tarx = ($^O eq 'solaris' ? 'gtar ' : 'tar ') . ( $dist_tarball =~ m/bz2$/ ? 'xjf' : 'xzf' ); if (-d $extracted_dir) { rmpath($extracted_dir); } my $extract_command = "cd @{[ $self->root ]}/build; $tarx $dist_tarball"; die "Failed to extract $dist_tarball" if system($extract_command); return $extracted_dir; } sub do_install_blead { my $self = shift; my $dist = shift; my $dist_name = 'perl'; my $dist_git_describe = 'blead'; my $dist_version = 'blead'; # We always blindly overwrite anything that's already there, # because blead is a moving target. my $dist_tarball = 'blead.tar.gz'; my $dist_tarball_path = joinpath($self->root, "dists", $dist_tarball); print "Fetching $dist_git_describe as $dist_tarball_path\n"; my $error = http_download("http://perl5.git.perl.org/perl.git/snapshot/$dist_tarball", $dist_tarball_path); if ($error) { die "\nERROR: Failed to download perl-blead tarball.\n\n"; } # Returns the wrong extracted dir for blead $self->do_extract_tarball($dist_tarball_path); my $build_dir = joinpath($self->root, "build"); local *DIRH; opendir DIRH, $build_dir or die "Couldn't open ${build_dir}: $!"; my @contents = readdir DIRH; closedir DIRH or warn "Couldn't close ${build_dir}: $!"; my @candidates = grep { m/^perl-[0-9a-f]{7,8}$/ } @contents; # Use a Schwartzian Transform in case there are lots of dirs that # look like "perl-$SHA1", which is what's inside blead.tar.gz, # so we stat each one only once. @candidates = map { $_->[0] } sort { $b->[1] <=> $a->[1] } # descending map { [ $_, (stat( joinpath($build_dir, $_) ))[9] ] } @candidates; my $dist_extracted_dir = joinpath($self->root, "build", $candidates[0]); # take the newest one $self->do_install_this($dist_extracted_dir, $dist_version, "$dist_name-$dist_version"); return; } 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 ($dist_tarball, $dist_tarball_url) = $self->perl_release($dist_version); my $dist_tarball_path = joinpath($self->root, "dists", $dist_tarball); if (-f $dist_tarball_path) { print "Use 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 if ($dist =~ /^(?:perl-?)?([\d._]+(?:-RC\d+)?|git|stable|blead)$/) { my $version = ($1 eq 'stable' ? $self->resolve_stable_version : $1); $dist = "perl-$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 ($version eq 'blead') { $self->do_install_blead($dist); } else { $self->do_install_release( $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($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) = @_; my ($dist_version) = $dist =~ /^ (?:perl-?)? (.*) $/xs; die "\"$dist\" does not look like a perl distribution name. " unless $dist_version =~ /^\d\./; my ($dist_tarball, $dist_tarball_url) = $self->perl_release($dist_version); my $dist_tarball_path = joinpath($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"; } } } sub purify { my ($self, $envname) = @_; my @paths = grep { index($_, $PERLBREW_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 (File::Basename::basename($dist_tarball_path) =~ m{perl-?(5.+)\.tar\.(gz|bz2)\Z}) { $dist_version = $1; $installation_name = "perl-${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\n"; } my $dist_extracted_path = $self->do_extract_tarball($dist_tarball_path); $self->do_install_this($dist_extracted_path, $dist_version, $installation_name); return; } sub do_install_this { my ($self, $dist_extracted_dir, $dist_version, $installation_name) = @_; my $variation = $self->{variation}; my $append = $self->{append}; $self->{dist_extracted_dir} = $dist_extracted_dir; $self->{log_file} = joinpath($self->root, "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}; $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\.1[13579]|git|blead/; unless (grep { /eval:scriptdir=/} @a_options) { push @a_options, "'eval:scriptdir=${perlpath}/bin'"; } my $version = perl_version_to_integer($dist_version); if (defined $version and $version < perl_version_to_integer( '5.6.0' ) ) { # ancient perls do not support -A for Configure @a_options = (); } print "Installing $dist_extracted_dir into " . $self->path_with_tilde("@{[ $self->root ]}/perls/$installation_name") . "\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->path_with_tilde($self->{log_file}) ]} INSTALL my @preconfigure_commands = ( "cd $dist_extracted_dir", "rm -f config.sh Policy.sh", $patchperl, ); 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 < perl_version_to_integer( '5.8.9' )) ? ("$^X -i -nle 'print unless /command-line/' makefile x2p/makefile") : () ); 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 = $self->{notest} ? "make install" : ("make $test_target", "make install"); @install_commands = join " && ", @install_commands unless($self->{force}); my $cmd = join " && ", ( @preconfigure_commands, @configure_commands, @build_commands, @install_commands ); unlink($self->{log_file}); 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); if ($self->do_system($cmd)) { my $newperl = joinpath($self->root, "perls", $installation_name, "bin", "perl"); unless (-e $newperl) { $self->run_command_symlink_executables($installation_name); } if ( $sitecustomize ) { my $capture = $self->do_capture("$newperl -V:sitelib"); my ($sitelib) = $capture =~ /sitelib='(.*)';/; mkpath($sitelib) unless -d $sitelib; my $target = "$sitelib/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> }; } print "$installation_name is successfully installed.\n"; } else { 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}) { 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 = joinpath($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); } mkpath("@{[ $self->root ]}/bin") unless -d "@{[ $self->root ]}/bin"; 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 (<$root/perls/*>) { my ($name) = $_ =~ m/\/([^\/]+$)/; my $executable = joinpath($_, 'bin', 'perl'); my $orig_version = `$executable -e 'print \$]'`; push @result, { name => $name, orig_version=> $orig_version, version => $self->format_perl_version($orig_version), is_current => ($self->current_perl eq $name) && !$self->env("PERLBREW_LIB"), libs => [ $self->local_libs($name) ], executable => $executable }; } return sort { $a->{orig_version} <=> $b->{orig_version} or $a->{name} cmp $b->{name} } @result; } sub local_libs { my ($self, $perl_name) = @_; my @libs = map { substr($_, length($PERLBREW_HOME) + 6) } <$PERLBREW_HOME/libs/*>; if ($perl_name) { @libs = grep { /^$perl_name\@/ } @libs; } my $current = $self->current_perl . '@' . ($self->env("PERLBREW_LIB") || ''); @libs = map { my ($p, $l) = split(/@/, $_); +{ name => $_, is_current => $_ eq $current, perl_name => $p, lib_name => $l } } @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"; } } my %env = ( PERLBREW_VERSION => $VERSION, PERLBREW_PATH => joinpath($self->root, "bin"), PERLBREW_MANPATH => "", PERLBREW_ROOT => $self->root ); if ($perl_name) { if(-d "@{[ $self->root ]}/perls/$perl_name/bin") { $env{PERLBREW_PERL} = $perl_name; $env{PERLBREW_PATH} .= ":" . joinpath($self->root, "perls", $perl_name, "bin"); $env{PERLBREW_MANPATH} = joinpath($self->root, "perls", $perl_name, "man") } if ($lib_name) { require local::lib; if ($ENV{PERL_LOCAL_LIB_ROOT} && $ENV{PERL_LOCAL_LIB_ROOT} =~ /^\Q$PERLBREW_HOME\E/ ) { my %deactivate_env = local::lib->build_deact_all_environment_vars_for($ENV{PERL_LOCAL_LIB_ROOT}); @env{keys %deactivate_env} = values %deactivate_env; } my $base = "$PERLBREW_HOME/libs/${perl_name}\@${lib_name}"; if (-d $base) { delete $ENV{PERL_LOCAL_LIB_ROOT}; @ENV{keys %env} = values %env; while (my ($k,$v) = each %ENV) { delete $ENV{$k} unless defined($v); } my %lib_env = local::lib->build_environment_vars_for($base, 0, 1); $env{PERLBREW_PATH} = joinpath($base, "bin") . ":" . $env{PERLBREW_PATH}; $env{PERLBREW_MANPATH} = joinpath($base, "man") . ":" . $env{PERLBREW_MANPATH}; $env{PERLBREW_LIB} = $lib_name; $env{PERL_MM_OPT} = $lib_env{PERL_MM_OPT}; $env{PERL_MB_OPT} = $lib_env{PERL_MB_OPT}; $env{PERL5LIB} = $lib_env{PERL5LIB}; $env{PERL_LOCAL_LIB_ROOT} = $lib_env{PERL_LOCAL_LIB_ROOT}; } } else { my $libroot = $self->env("PERL_LOCAL_LIB_ROOT"); if ($libroot && $libroot =~ /^\Q$PERLBREW_HOME\E/) { require local::lib; my %deactivate_env = local::lib->build_deact_all_environment_vars_for($libroot); @env{keys %deactivate_env} = values %deactivate_env; $env{PERLBREW_LIB} = undef; } if (my $perl5lib = $self->env("PERL5LIB")) { my @perl5libs = split $Config{path_sep} => $perl5lib; my @pristine_perl5libs = grep { !/^\Q$PERLBREW_HOME\E/ } @perl5libs; if (@pristine_perl5libs) { $env{PERL5LIB} = join $Config{path_sep}, @pristine_perl5libs; } else { $env{PERL5LIB} = undef; } } } } else { my $libroot = $self->env("PERL_LOCAL_LIB_ROOT"); if ($libroot && $libroot =~ /^\Q$PERLBREW_HOME\E/) { require local::lib; my %deactivate_env = local::lib->build_deact_all_environment_vars_for($libroot); @env{keys %deactivate_env} = values %deactivate_env; $env{PERLBREW_LIB} = undef; } $env{PERLBREW_PERL} = undef; } return %env; } sub run_command_list { my $self = shift; for my $i ( $self->installed_perls ) { print $i->{is_current} ? '* ': ' ', $i->{name}, (index($i->{name}, $i->{version}) < 0) ? " ($i->{version})" : "", "\n"; 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 } } elsif ($shell =~ /\/bash$/) { $shell_opt = "--noprofile --norc"; } 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_perl; 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_perl; 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 joinpath($self->root, "perls", $dist); if ($self->env("PERLBREW_BASHRC_VERSION")) { local $ENV{PERLBREW_PERL} = $dist; my $HOME = $self->env('HOME'); my $pb_home = $self->env("PERLBREW_HOME") || $PERLBREW_HOME; mkpath($pb_home); system("$0 env $dist > " . joinpath($pb_home, "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->env("PERLBREW_HOME") || $PERLBREW_HOME; mkpath($pb_home); system("env PERLBREW_PERL= $0 env > " . joinpath($pb_home, "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_mirror { my($self) = @_; print "Fetching mirror list\n"; my $raw = http_get("http://search.cpan.org/mirror"); unless ($raw) { die "\nERROR: Failed to retrieve the mirror list.\n\n"; } my $found; my @mirrors; foreach my $line ( split m{\n}, $raw ) { $found = 1 if $line =~ m{}; if ( $line =~ m{} ) { my $url = $1; my $name = $2; $name =~ s/&#(\d+);/chr $1/seg; $url =~ s/&#(\d+);/chr $1/seg; push @mirrors, { url => $url, name => $name }; } } require ExtUtils::MakeMaker; my $select; my $max = @mirrors; my $id = 0; while ( @mirrors ) { my @page = splice(@mirrors,0,20); my $base = $id; printf "[% 3d] %s\n", ++$id, $_->{name} for @page; my $remaining = $max - $id; my $ask = "Select a mirror by number or press enter to see the rest " . "($remaining more) [q to quit, m for manual entry]"; my $val = ExtUtils::MakeMaker::prompt( $ask ); if ( ! length $val ) { next } elsif ( $val eq 'q' ) { last } elsif ( $val eq 'm' ) { my $url = ExtUtils::MakeMaker::prompt("Enter the URL of your CPAN mirror:"); my $name = ExtUtils::MakeMaker::prompt("Enter a Name: [default: My CPAN Mirror]") || "My CPAN Mirror"; $select = { name => $name, url => $url }; last; } elsif ( not $val =~ /\s*(\d+)\s*/ ) { die "Invalid answer: must be 'q', 'm' or a number\n"; } elsif (1 <= $val and $val <= $max) { $select = $page[ $val - 1 - $base ]; last; } else { die "Invalid ID: must be between 1 and $max\n"; } } die "You didn't select a mirror!\n" if ! $select; print "Selected $select->{name} ($select->{url}) as the mirror\n"; my $conf = $self->config; $conf->{mirror} = $select; $self->_save_config; return; } sub run_command_env { my($self, $name) = @_; my %env = $self->perlbrew_env($name); if ($self->env('SHELL') =~ /(ba|k|z|\/)sh\d?$/) { for my $k (sort keys %env) { my $v = $env{$k}; if (defined $v) { $v =~ s/(\\")/\\$1/g; print "export $k=\"$v\"\n"; } else { print "unset $k\n"; } } } else { for my $k (sort keys %env) { my $v = $env{$k}; if (defined $v) { $v =~ s/(\\")/\\$1/g; print "setenv $k \"$v\"\n"; } else { print "unsetenv $k\n"; } } } } sub run_command_symlink_executables { my($self, @perls) = @_; my $root = $self->root; unless (@perls) { @perls = map { m{/([^/]+)$} } grep { -d $_ && ! -l $_ } <$root/perls/*>; } for my $perl (@perls) { for my $executable (<$root/perls/$perl/bin/*>) { my ($name, $version) = $executable =~ m/bin\/(.+?)(5\.\d.*)?$/; system("ln -fs $executable $root/perls/$perl/bin/$name") if $version; } } } sub run_command_install_patchperl { my ($self) = @_; $self->do_install_program_from_url( 'https://raw.github.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.github.com/miyagawa/cpanminus/master/cpanm' => 'cpanm'); } sub run_command_self_upgrade { my ($self) = @_; my $TMPDIR = $ENV{TMPDIR} || "/tmp"; my $TMP_PERLBREW = joinpath($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('http://get.perlbrew.pl', 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"; unlink $TMP_PERLBREW; } sub run_command_uninstall { my ( $self, $target ) = @_; unless($target) { $self->run_command_help("uninstall"); exit(-1); } my $dir = "@{[ $self->root ]}/perls/$target"; if (-l $dir) { die "\nThe given name `$target` is an alias, not a real installation. Cannot perform uninstall.\nTo delete the alias, run:\n\n perlbrew alias delete $target\n\n"; } unless(-d $dir) { die "'$target' is not installed\n"; } exec 'rm', '-rf', $dir; } 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'); $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} =~ / /) ? 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 (0 == @exec_with) { print "No perl installation found.\n" unless $self->{quiet}; } 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{ keys %env } = values %env; local $ENV{PATH} = join(':', $env{PERLBREW_PATH}, $ENV{PATH}); local $ENV{MANPATH} = join(':', $env{PERLBREW_MANPATH}, $ENV{MANPATH}||""); local $ENV{PERL5LIB} = $env{PERL5LIB} || ""; print "$i->{name}\n==========\n" unless $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; print "Command terminated with non-zero status.\n" unless $self->{quiet}; 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\n" unless $self->{quiet}; } $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/*>; for my $dir (@build_dirs) { print "Removing $dir\n"; rmpath($dir); } my @tarballs = <$root/dists/*>; for my $file ( @tarballs ) { print "Removing $file\n"; unlink($file); } print "\nDone\n"; } sub run_command_alias { my ($self, $cmd, $name, $alias) = @_; if (!$cmd) { print < [] perlbrew alias create perlbrew alias delete perlbrew alias rename USAGE return; } my $path_name = joinpath($self->root, "perls", $name); my $path_alias = joinpath($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"; } unlink($path_alias) if -e $path_alias; symlink($path_name, $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"; } unlink($path_name); } 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 lib_usage { my $usage = <<'USAGE'; Usage: perlbrew lib [ ...] perlbrew lib list perlbrew lib create nobita perlbrew lib create perl-5.14.2@nobita perlbrew use perl-5.14.2@nobita perlbrew lib delete perl-5.12.3@nobita shizuka USAGE return $usage; } sub run_command_lib { my ($self, $subcommand, @args) = @_; unless ($subcommand) { print lib_usage; return; } 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", lib_usage unless $name; $name =~ s/^/@/ unless $name =~ /@/; my ($perl_name, $lib_name) = $self->resolve_installation_name($name); if (!$perl_name) { my ($perl_name, $lib_name) = split('@', $name); die "ERROR: '$perl_name' is not installed yet, '$name' cannot be created.\n"; } my $fullname = $perl_name . '@' . $lib_name; my $dir = joinpath($PERLBREW_HOME, "libs", $fullname); if (-d $dir) { die "$fullname is already there.\n"; } mkpath($dir); 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", lib_usage unless $name; $name =~ s/^/@/ unless $name =~ /@/; my ($perl_name, $lib_name) = $self->resolve_installation_name($name); if (!$perl_name) { } my $fullname = $perl_name . '@' . $lib_name; my $current = $self->current_perl . '@' . ($self->env("PERLBREW_LIB") || ""); my $dir = joinpath($PERLBREW_HOME, "libs", $fullname); if (-d $dir) { if ($fullname eq $current) { die "$fullname is currently being used in the current shell, it cannot be deleted.\n"; } rmpath($dir); 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 $current = ""; if ($self->current_perl && $self->env("PERLBREW_LIB")) { $current = $self->current_perl . "@" . $self->env("PERLBREW_LIB"); } my $dir = joinpath($PERLBREW_HOME, "libs"); return unless -d $dir; opendir my $dh, $dir or die "open $dir failed: $!"; my @libs = grep { !/^\./ && /\@/ } readdir($dh); 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; $self->do_install_release($dist, $dist_version); } sub run_command_list_modules { my ($self) = @_; my $class = ref($self) || __PACKAGE__; my $app = $class->new( qw(--quiet exec --with), $self->current_env, 'perl', '-MExtUtils::Installed', '-le', 'BEGIN{@INC=grep {$_ ne q!.!} @INC}; print for ExtUtils::Installed->new->modules;' ); $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) = split('@', $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; } sub format_info_output { my ($self) = @_; my $out = ''; $out .= "Current perl:\n"; if ($self->current_perl) { $out .= " Name: " . $self->current_env . "\n"; $out .= " Path: " . $self->current_perl_executable . "\n"; $out .= " Config: " . $self->configure_args( $self->current_perl ) . "\n"; $out .= join('', " Compiled at: ", (map { / Compiled at (.+)\n/ ? $1 : () } `@{[ $self->current_perl_executable ]} -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"; } $out; } sub run_command_info { my ($self) = @_; print $self->format_info_output; } sub config { my($self) = @_; $self->_load_config if ! $CONFIG; return $CONFIG; } sub config_file { my ($self) = @_; joinpath( $self->root, 'Config.pm' ); } sub _save_config { my($self) = @_; require Data::Dumper; open my $FH, '>', $self->config_file or die "Unable to open config (@{[ $self->config_file ]}): $!"; my $d = Data::Dumper->new([$CONFIG],['App::perlbrew::CONFIG']); print $FH $d->Dump; close $FH; } sub _load_config { my($self) = @_; if ( ! -e $self->config_file ) { local $CONFIG = {} if ! $CONFIG; $self->_save_config; } open my $FH, '<', $self->config_file or die "Unable to open config (@{[ $self->config_file ]}): $!\n"; my $raw = do { local $/; my $rv = <$FH>; $rv }; close $FH; my $rv = eval $raw; if ( $@ ) { warn "Error loading conf: $@\n"; $CONFIG = {}; return; } $CONFIG = {} if ! $CONFIG; return; } sub BASHRC_CONTENT() { return "export PERLBREW_BASHRC_VERSION=$VERSION\n\n" . <<'RC'; __perlbrew_reinit() { if [[ ! -d "$PERLBREW_HOME" ]]; then mkdir -p "$PERLBREW_HOME" fi 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_set_path () { 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 [ -n "$PERLBREW_MANPATH" ]; then export MANPATH="$PERLBREW_MANPATH:$MANPATH_WITHOUT_PERLBREW" else export MANPATH="$MANPATH_WITHOUT_PERLBREW" fi unset MANPATH_WITHOUT_PERLBREW PATH_WITHOUT_PERLBREW=$(eval $perlbrew_command display-pristine-path) if [ -n "$PERLBREW_PATH" ]; then export PATH=${PERLBREW_PATH}:${PATH_WITHOUT_PERLBREW} else export PATH=${PERLBREW_ROOT}/bin:${PATH_WITHOUT_PERLBREW} fi unset PATH_WITHOUT_PERLBREW hash -r } __perlbrew_set_env() { local code="$($perlbrew_command env $@)" local exit_status="$?" if [[ $exit_status -eq 0 ]] ; then eval "$code" else return $exit_status fi } __perlbrew_activate() { [[ -n $(alias perl 2>/dev/null) ]] && unalias perl 2>/dev/null if [[ -n "$PERLBREW_PERL" ]]; then if [[ -z "$PERLBREW_LIB" ]]; then __perlbrew_set_env $PERLBREW_PERL else __perlbrew_set_env $PERLBREW_PERL@$PERLBREW_LIB fi 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 if [[ -z "$PERLBREW_PERL" ]] ; then echo "Currently using system perl" else echo "Currently using $PERLBREW_PERL" fi else __perlbrew_set_env "$2" exit_status="$?" if [[ $exit_status -eq 0 ]] then __perlbrew_set_path fi fi ;; (switch) if [[ -z "$2" ]] ; then command perlbrew switch else perlbrew use $2 exit_status=$? if [[ ${exit_status} -eq 0 ]]; then __perlbrew_reinit $2 fi 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 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`" ) 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 $argv 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_CSHRC_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 INSTALLATION_FAILURE_MESSAGE { my ($self) = @_; return <{log_file} If some perl tests failed and you still want 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 command 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 $HOME =head1 SYNOPSIS # Installation curl -kL http://install.perlbrew.pl | bash # Initialize perlbrew init # Pick a preferred CPAN mirror perlbrew mirror # See what is available perlbrew available # Install some Perls perlbrew install 5.14.0 perlbrew install perl-5.8.1 perlbrew install perl-5.13.6 # See what were installed perlbrew list # Switch perl in the $PATH perlbrew switch perl-5.12.2 perl -v # 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 $]' =head1 DESCRIPTION perlbrew is a program to automate the building and installation of perl in an easy way. It installs everything to C<~/perl5/perlbrew>, and requires you to tweak your PATH by including a bashrc/cshrc file it provides. You then can benefit from not having to run 'sudo' commands to install cpan modules because those are installed inside your HOME too. It provides multiple isolated perl environments, and a mechanism for you to switch between them. For the documentation of perlbrew usage see L command on CPAN, or by running C. The following documentation features the API of C module, and may not be remotely close to what your want to read. =head1 INSTALLATION It is the simplest to use the perlbrew installer, just paste this statement to your terminal: curl -kL http://install.perlbrew.pl | bash Or this one, if you have C (default on FreeBSD): fetch -o- http://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 packed version of C 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 "perlbrew root". If you need to set it to somewhere else because, say, your HOME has limited quota, you can do that by setting C environment variable before running the installer: export PERLBREW_ROOT=/opt/perl5 curl -kL http://install.perlbrew.pl | bash 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 `cpan App::perlbrew` again. =head1 METHODS =over 4 =item (Str) current_perl Return the "current perl" object attribute string, or, if absent, the value of PERLBREW_PERL environment variable. =item (Str) current_perl (Str) Set the "current_perl" object attribute to the given value. =back =head1 PROJECT DEVELOPMENT perlbrew project 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, 2011, 2012 Kang-min Liu C<< >>. =head1 LICENCE The MIT License =head1 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 App-perlbrew-0.66/inc/Module/000755 000765 000024 00000000000 12177031266 016260 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/inc/Module/Install/000755 000765 000024 00000000000 12177031266 017666 5ustar00gugodstaff000000 000000 App-perlbrew-0.66/inc/Module/Install.pm000644 000765 000024 00000030135 12177031264 020224 0ustar00gugodstaff000000 000000 #line 1 package Module::Install; # For any maintainers: # The load order for Module::Install is a bit magic. # It goes something like this... # # IF ( host has Module::Install installed, creating author mode ) { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install # 3. The installed version of inc::Module::Install loads # 4. inc::Module::Install calls "require Module::Install" # 5. The ./inc/ version of Module::Install loads # } ELSE { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install # 3. The ./inc/ version of Module::Install loads # } use 5.005; use strict 'vars'; use Cwd (); use File::Find (); use File::Path (); use vars qw{$VERSION $MAIN}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '1.06'; # Storage for the pseudo-singleton $MAIN = undef; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; #------------------------------------------------------------- # all of the following checks should be included in import(), # to allow "eval 'require Module::Install; 1' to test # installation of Module::Install. (RT #51267) #------------------------------------------------------------- # Whether or not inc::Module::Install is actually loaded, the # $INC{inc/Module/Install.pm} is what will still get set as long as # the caller loaded module this in the documented manner. # If not set, the caller may NOT have loaded the bundled version, and thus # they may not have a MI version that works with the Makefile.PL. This would # result in false errors or unexpected behaviour. And we don't want that. my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm'; unless ( $INC{$file} ) { die <<"END_DIE" } Please invoke ${\__PACKAGE__} with: use inc::${\__PACKAGE__}; not: use ${\__PACKAGE__}; END_DIE # This reportedly fixes a rare Win32 UTC file time issue, but # as this is a non-cross-platform XS module not in the core, # we shouldn't really depend on it. See RT #24194 for detail. # (Also, this module only supports Perl 5.6 and above). eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006; # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 ) { my $s = (stat($0))[9]; # If the modification time is only slightly in the future, # sleep briefly to remove the problem. my $a = $s - time; if ( $a > 0 and $a < 5 ) { sleep 5 } # Too far in the future, throw an error. my $t = time; if ( $s > $t ) { die <<"END_DIE" } Your installer $0 has a modification time in the future ($s > $t). This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE } # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE #------------------------------------------------------------- # To save some more typing in Module::Install installers, every... # use inc::Module::Install # ...also acts as an implicit use strict. $^H |= strict::bits(qw(refs subs vars)); #------------------------------------------------------------- unless ( -f $self->{file} ) { foreach my $key (keys %INC) { delete $INC{$key} if $key =~ /Module\/Install/; } local $^W; require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } local $^W; *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{'inc/Module/Install.pm'}; delete $INC{'Module/Install.pm'}; # Save to the singleton $MAIN = $self; return 1; } sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::cwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::cwd(); if ( my $code = $sym->{$pwd} ) { # Delegate back to parent dirs goto &$code unless $cwd eq $pwd; } unless ($$sym =~ s/([^:]+)$//) { # XXX: it looks like we can't retrieve the missing function # via $$sym (usually $main::AUTOLOAD) in this case. # I'm still wondering if we should slurp Makefile.PL to # get some context or not ... my ($package, $file, $line) = caller; die <<"EOT"; Unknown function is found at $file line $line. Execution of $file aborted due to runtime errors. If you're a contributor to a project, you may need to install some Module::Install extensions from CPAN (or other repository). If you're a user of a module, please contact the author. EOT } my $method = $1; if ( uc($method) eq $method ) { # Do nothing return; } elsif ( $method =~ /^_/ and $self->can($method) ) { # Dispatch to the root M:I class return $self->$method(@_); } # Dispatch to the appropriate plugin unshift @_, ( $self, $1 ); goto &{$self->can('call')}; }; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { @exts = $self->{admin}->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { local $^W; *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; delete $INC{'FindBin.pm'}; { # to suppress the redefine warning local $SIG{__WARN__} = sub {}; require FindBin; } # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; my $should_reload = 0; unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; $should_reload = 1; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { local $^W; require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = $should_reload ? delete $INC{$file} : $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split //, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Common Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _read { local *FH; open( FH, '<', $_[0] ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_NEW sub _read { local *FH; open( FH, "< $_[0]" ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_OLD sub _readperl { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s; $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg; return $string; } sub _readpod { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; return $string if $_[0] =~ /\.pod\z/; $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg; $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg; $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg; $string =~ s/^\n+//s; return $string; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _write { local *FH; open( FH, '>', $_[0] ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_NEW sub _write { local *FH; open( FH, "> $_[0]" ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_OLD # _version is for processing module versions (eg, 1.03_05) not # Perl versions (eg, 5.8.1). sub _version ($) { my $s = shift || 0; my $d =()= $s =~ /(\.)/g; if ( $d >= 2 ) { # Normalise multipart versions $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg; } $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } sub _cmp ($$) { _version($_[1]) <=> _version($_[2]); } # Cloned from Params::Util::_CLASS sub _CLASS ($) { ( defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s ) ? $_[0] : undef; } 1; # Copyright 2008 - 2012 Adam Kennedy. App-perlbrew-0.66/inc/Module/Install/Base.pm000644 000765 000024 00000002147 12177031265 021101 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Base; use strict 'vars'; use vars qw{$VERSION}; BEGIN { $VERSION = '1.06'; } # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } #line 42 sub new { my $class = shift; unless ( defined &{"${class}::call"} ) { *{"${class}::call"} = sub { shift->_top->call(@_) }; } unless ( defined &{"${class}::load"} ) { *{"${class}::load"} = sub { shift->_top->load(@_) }; } bless { @_ }, $class; } #line 61 sub AUTOLOAD { local $@; my $func = eval { shift->_top->autoload } or return; goto &$func; } #line 75 sub _top { $_[0]->{_top}; } #line 90 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } #line 106 sub is_admin { ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); } sub DESTROY {} package Module::Install::Base::FakeAdmin; use vars qw{$VERSION}; BEGIN { $VERSION = $Module::Install::Base::VERSION; } my $fake; sub new { $fake ||= bless(\@_, $_[0]); } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 159 App-perlbrew-0.66/inc/Module/Install/Can.pm000644 000765 000024 00000006157 12177031265 020735 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Can; use strict; use Config (); use ExtUtils::MakeMaker (); use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # check if we can load some module ### Upgrade this to not have to load the module if possible sub can_use { my ($self, $mod, $ver) = @_; $mod =~ s{::|\\}{/}g; $mod .= '.pm' unless $mod =~ /\.pm$/i; my $pkg = $mod; $pkg =~ s{/}{::}g; $pkg =~ s{\.pm$}{}i; local $@; eval { require $mod; $pkg->VERSION($ver || 0); 1 }; } # Check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; require File::Spec; my $abs = File::Spec->catfile($dir, $cmd); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # Can our C compiler environment build XS files sub can_xs { my $self = shift; # Ensure we have the CBuilder module $self->configure_requires( 'ExtUtils::CBuilder' => 0.27 ); # Do we have the configure_requires checker? local $@; eval "require ExtUtils::CBuilder;"; if ( $@ ) { # They don't obey configure_requires, so it is # someone old and delicate. Try to avoid hurting # them by falling back to an older simpler test. return $self->can_cc(); } # Do we have a working C compiler my $builder = ExtUtils::CBuilder->new( quiet => 1, ); unless ( $builder->have_compiler ) { # No working C compiler return 0; } # Write a C file representative of what XS becomes require File::Temp; my ( $FH, $tmpfile ) = File::Temp::tempfile( "compilexs-XXXXX", SUFFIX => '.c', ); binmode $FH; print $FH <<'END_C'; #include "EXTERN.h" #include "perl.h" #include "XSUB.h" int main(int argc, char **argv) { return 0; } int boot_sanexs() { return 1; } END_C close $FH; # Can the C compiler access the same headers XS does my @libs = (); my $object = undef; eval { local $^W = 0; $object = $builder->compile( source => $tmpfile, ); @libs = $builder->link( objects => $object, module_name => 'sanexs', ); }; my $result = $@ ? 0 : 1; # Clean up all the build files foreach ( $tmpfile, $object, @libs ) { next unless defined $_; 1 while unlink; } return $result; } # Can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 236 App-perlbrew-0.66/inc/Module/Install/Fetch.pm000644 000765 000024 00000004627 12177031265 021265 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Fetch; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; App-perlbrew-0.66/inc/Module/Install/Makefile.pm000644 000765 000024 00000027437 12177031265 021755 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Makefile; use strict 'vars'; use ExtUtils::MakeMaker (); use Module::Install::Base (); use Fcntl qw/:flock :seek/; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing or non-interactive session, always use defaults if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } # Store a cleaned up version of the MakeMaker version, # since we need to behave differently in a variety of # ways based on the MM version. my $makemaker = eval $ExtUtils::MakeMaker::VERSION; # If we are passed a param, do a "newer than" comparison. # Otherwise, just return the MakeMaker version. sub makemaker { ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 } # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified # as we only need to know here whether the attribute is an array # or a hash or something else (which may or may not be appendable). my %makemaker_argtype = ( C => 'ARRAY', CONFIG => 'ARRAY', # CONFIGURE => 'CODE', # ignore DIR => 'ARRAY', DL_FUNCS => 'HASH', DL_VARS => 'ARRAY', EXCLUDE_EXT => 'ARRAY', EXE_FILES => 'ARRAY', FUNCLIST => 'ARRAY', H => 'ARRAY', IMPORTS => 'HASH', INCLUDE_EXT => 'ARRAY', LIBS => 'ARRAY', # ignore '' MAN1PODS => 'HASH', MAN3PODS => 'HASH', META_ADD => 'HASH', META_MERGE => 'HASH', PL_FILES => 'HASH', PM => 'HASH', PMLIBDIRS => 'ARRAY', PMLIBPARENTDIRS => 'ARRAY', PREREQ_PM => 'HASH', CONFIGURE_REQUIRES => 'HASH', SKIP => 'ARRAY', TYPEMAPS => 'ARRAY', XS => 'HASH', # VERSION => ['version',''], # ignore # _KEEP_AFTER_FLUSH => '', clean => 'HASH', depend => 'HASH', dist => 'HASH', dynamic_lib=> 'HASH', linkext => 'HASH', macro => 'HASH', postamble => 'HASH', realclean => 'HASH', test => 'HASH', tool_autosplit => 'HASH', # special cases where you can use makemaker_append CCFLAGS => 'APPENDABLE', DEFINE => 'APPENDABLE', INC => 'APPENDABLE', LDDLFLAGS => 'APPENDABLE', LDFROM => 'APPENDABLE', ); sub makemaker_args { my ($self, %new_args) = @_; my $args = ( $self->{makemaker_args} ||= {} ); foreach my $key (keys %new_args) { if ($makemaker_argtype{$key}) { if ($makemaker_argtype{$key} eq 'ARRAY') { $args->{$key} = [] unless defined $args->{$key}; unless (ref $args->{$key} eq 'ARRAY') { $args->{$key} = [$args->{$key}] } push @{$args->{$key}}, ref $new_args{$key} eq 'ARRAY' ? @{$new_args{$key}} : $new_args{$key}; } elsif ($makemaker_argtype{$key} eq 'HASH') { $args->{$key} = {} unless defined $args->{$key}; foreach my $skey (keys %{ $new_args{$key} }) { $args->{$key}{$skey} = $new_args{$key}{$skey}; } } elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { $self->makemaker_append($key => $new_args{$key}); } } else { if (defined $args->{$key}) { warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; } $args->{$key} = $new_args{$key}; } } return $args; } # For mm args that take multiple space-seperated args, # append an argument to the current list. sub makemaker_append { my $self = shift; my $name = shift; my $args = $self->makemaker_args; $args->{$name} = defined $args->{$name} ? join( ' ', $args->{$name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub _wanted_t { } sub tests_recursive { my $self = shift; my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } my %tests = map { $_ => 1 } split / /, ($self->tests || ''); require File::Find; File::Find::find( sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 }, $dir ); $self->tests( join ' ', sort keys %tests ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Check the current Perl version my $perl_version = $self->perl_version; if ( $perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } # Make sure we have a new enough MakeMaker require ExtUtils::MakeMaker; if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { # This previous attempted to inherit the version of # ExtUtils::MakeMaker in use by the module author, but this # was found to be untenable as some authors build releases # using future dev versions of EU:MM that nobody else has. # Instead, #toolchain suggests we use 6.59 which is the most # stable version on CPAN at time of writing and is, to quote # ribasushi, "not terminally fucked, > and tested enough". # TODO: We will now need to maintain this over time to push # the version up as new versions are released. $self->build_requires( 'ExtUtils::MakeMaker' => 6.59 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.59 ); } else { # Allow legacy-compatibility with 5.005 by depending on the # most recent EU:MM that supported 5.005. $self->build_requires( 'ExtUtils::MakeMaker' => 6.36 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.36 ); } # Generate the MakeMaker params my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{NAME} =~ s/-/::/g; $args->{VERSION} = $self->version or die <<'EOT'; ERROR: Can't determine distribution version. Please specify it explicitly via 'version' in Makefile.PL, or set a valid $VERSION in a module, and provide its file path via 'version_from' (or 'all_from' if you prefer) in Makefile.PL. EOT if ( $self->tests ) { my @tests = split ' ', $self->tests; my %seen; $args->{test} = { TESTS => (join ' ', grep {!$seen{$_}++} @tests), }; } elsif ( $Module::Install::ExtraTests::use_extratests ) { # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness. # So, just ignore our xt tests here. } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { $args->{test} = { TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), }; } if ( $] >= 5.005 ) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = join ', ', @{$self->author || []}; } if ( $self->makemaker(6.10) ) { $args->{NO_META} = 1; #$args->{NO_MYMETA} = 1; } if ( $self->makemaker(6.17) and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } if ( $self->makemaker(6.31) and $self->license ) { $args->{LICENSE} = $self->license; } my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # Merge both kinds of requires into BUILD_REQUIRES my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); %$build_prereq = ( %$build_prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->configure_requires, $self->build_requires) ); # Remove any reference to perl, BUILD_REQUIRES doesn't support it delete $args->{BUILD_REQUIRES}->{perl}; # Delete bundled dists from prereq_pm, add it to Makefile DIR my $subdirs = ($args->{DIR} || []); if ($self->bundles) { my %processed; foreach my $bundle (@{ $self->bundles }) { my ($mod_name, $dist_dir) = @$bundle; delete $prereq->{$mod_name}; $dist_dir = File::Basename::basename($dist_dir); # dir for building this module if (not exists $processed{$dist_dir}) { if (-d $dist_dir) { # List as sub-directory to be processed by make push @$subdirs, $dist_dir; } # Else do nothing: the module is already present on the system $processed{$dist_dir} = undef; } } } unless ( $self->makemaker('6.55_03') ) { %$prereq = (%$prereq,%$build_prereq); delete $args->{BUILD_REQUIRES}; } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; if ( $self->makemaker(6.48) ) { $args->{MIN_PERL_VERSION} = $perl_version; } } if ($self->installdirs) { warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; $args->{INSTALLDIRS} = $self->installdirs; } my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) } keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if ( my $preop = $self->admin->preop($user_preop) ) { foreach my $key ( keys %$preop ) { $args{dist}->{$key} = $preop->{$key}; } } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; eval { flock MAKEFILE, LOCK_EX }; my $makefile = do { local $/; }; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; seek MAKEFILE, 0, SEEK_SET; truncate MAKEFILE, 0; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 544 App-perlbrew-0.66/inc/Module/Install/Metadata.pm000644 000765 000024 00000043277 12177031265 021760 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } my @boolean_keys = qw{ sign }; my @scalar_keys = qw{ name module_name abstract version distribution_type tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles resources }; my @resource_keys = qw{ homepage bugtracker repository }; my @array_keys = qw{ keywords author }; *authors = \&author; sub Meta { shift } sub Meta_BooleanKeys { @boolean_keys } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } sub Meta_ResourceKeys { @resource_keys } sub Meta_ArrayKeys { @array_keys } foreach my $key ( @boolean_keys ) { *$key = sub { my $self = shift; if ( defined wantarray and not @_ ) { return $self->{values}->{$key}; } $self->{values}->{$key} = ( @_ ? $_[0] : 1 ); return $self; }; } foreach my $key ( @scalar_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} = shift; return $self; }; } foreach my $key ( @array_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} ||= []; push @{$self->{values}->{$key}}, @_; return $self; }; } foreach my $key ( @resource_keys ) { *$key = sub { my $self = shift; unless ( @_ ) { return () unless $self->{values}->{resources}; return map { $_->[1] } grep { $_->[0] eq $key } @{ $self->{values}->{resources} }; } return $self->{values}->{resources}->{$key} unless @_; my $uri = shift or die( "Did not provide a value to $key()" ); $self->resources( $key => $uri ); return 1; }; } foreach my $key ( grep { $_ ne "resources" } @tuple_keys) { *$key = sub { my $self = shift; return $self->{values}->{$key} unless @_; my @added; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @added, [ $module, $version ]; } push @{ $self->{values}->{$key} }, @added; return map {@$_} @added; }; } # Resource handling my %lc_resource = map { $_ => 1 } qw{ homepage license bugtracker repository }; sub resources { my $self = shift; while ( @_ ) { my $name = shift or last; my $value = shift or next; if ( $name eq lc $name and ! $lc_resource{$name} ) { die("Unsupported reserved lowercase resource '$name'"); } $self->{values}->{resources} ||= []; push @{ $self->{values}->{resources} }, [ $name, $value ]; } $self->{values}->{resources}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub dynamic_config { my $self = shift; my $value = @_ ? shift : 1; if ( $self->{values}->{dynamic_config} ) { # Once dynamic we never change to static, for safety return 0; } $self->{values}->{dynamic_config} = $value ? 1 : 0; return 1; } # Convenience command sub static_config { shift->dynamic_config(0); } sub perl_version { my $self = shift; return $self->{values}->{perl_version} unless @_; my $version = shift or die( "Did not provide a value to perl_version()" ); # Normalize the version $version = $self->_perl_version($version); # We don't support the really old versions unless ( $version >= 5.005 ) { die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; } $self->{values}->{perl_version} = $version; } sub all_from { my ( $self, $file ) = @_; unless ( defined($file) ) { my $name = $self->name or die( "all_from called with no args without setting name() first" ); $file = join('/', 'lib', split(/-/, $name)) . '.pm'; $file =~ s{.*/}{} unless -e $file; unless ( -e $file ) { die("all_from cannot find $file from $name"); } } unless ( -f $file ) { die("The path '$file' does not exist, or is not a file"); } $self->{values}{all_from} = $file; # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless @{$self->author || []}; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}->{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}->{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}->{no_index}->{$type} }, @_ if $type; return $self->{values}->{no_index}; } sub read { my $self = shift; $self->include_deps( 'YAML::Tiny', 0 ); require YAML::Tiny; my $data = YAML::Tiny::LoadFile('META.yml'); # Call methods explicitly in case user has already set some values. while ( my ( $key, $value ) = each %$data ) { next unless $self->can($key); if ( ref $value eq 'HASH' ) { while ( my ( $module, $version ) = each %$value ) { $self->can($key)->($self, $module => $version ); } } else { $self->can($key)->($self, $value); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); # for version integrity check $self->makemaker_args( VERSION_FROM => $file ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } # Add both distribution and module name sub name_from { my ($self, $file) = @_; if ( Module::Install::_read($file) =~ m/ ^ \s* package \s* ([\w:]+) \s* ; /ixms ) { my ($name, $module_name) = ($1, $1); $name =~ s{::}{-}g; $self->name($name); unless ( $self->module_name ) { $self->module_name($module_name); } } else { die("Cannot determine name from $file\n"); } } sub _extract_perl_version { if ( $_[0] =~ m/ ^\s* (?:use|require) \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; return $perl_version; } else { return; } } sub perl_version_from { my $self = shift; my $perl_version=_extract_perl_version(Module::Install::_read($_[0])); if ($perl_version) { $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; # XXX: ugly but should work anyway... if (eval "require Pod::Escapes; 1") { # Pod::Escapes has a mapping table. # It's in core of perl >= 5.9.3, and should be installed # as one of the Pod::Simple's prereqs, which is a prereq # of Pod::Text 3.x (see also below). $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $Pod::Escapes::Name2character_number{$1} ? chr($Pod::Escapes::Name2character_number{$1}) : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) { # Pod::Text < 3.0 has yet another mapping table, # though the table name of 2.x and 1.x are different. # (1.x is in core of Perl < 5.6, 2.x is in core of # Perl < 5.9.3) my $mapping = ($Pod::Text::VERSION < 2) ? \%Pod::Text::HTML_Escapes : \%Pod::Text::ESCAPES; $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $mapping->{$1} ? $mapping->{$1} : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } else { $author =~ s{E}{<}g; $author =~ s{E}{>}g; } $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } #Stolen from M::B my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php', lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html', bsd => 'http://opensource.org/licenses/bsd-license.php', gpl => 'http://opensource.org/licenses/gpl-license.php', gpl2 => 'http://opensource.org/licenses/gpl-2.0.php', gpl3 => 'http://opensource.org/licenses/gpl-3.0.html', mit => 'http://opensource.org/licenses/mit-license.php', mozilla => 'http://opensource.org/licenses/mozilla1.1.php', open_source => undef, unrestricted => undef, restrictive => undef, unknown => undef, ); sub license { my $self = shift; return $self->{values}->{license} unless @_; my $license = shift or die( 'Did not provide a value to license()' ); $license = __extract_license($license) || lc $license; $self->{values}->{license} = $license; # Automatically fill in license URLs if ( $license_urls{$license} ) { $self->resources( license => $license_urls{$license} ); } return 1; } sub _extract_license { my $pod = shift; my $matched; return __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?) (=head \d.*|=cut.*|)\z /xms ) || __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?) (=head \d.*|=cut.*|)\z /xms ); } sub __extract_license { my $license_text = shift or return; my @phrases = ( '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1, '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1, 'Artistic and GPL' => 'perl', 1, 'GNU general public license' => 'gpl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser general public license' => 'lgpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'GNU library general public license' => 'lgpl', 1, 'GNU library public license' => 'lgpl', 1, 'GNU Free Documentation license' => 'unrestricted', 1, 'GNU Affero General Public License' => 'open_source', 1, '(?:Free)?BSD license' => 'bsd', 1, 'Artistic license 2\.0' => 'artistic_2', 1, 'Artistic license' => 'artistic', 1, 'Apache (?:Software )?license' => 'apache', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'Mozilla Public License' => 'mozilla', 1, 'Q Public License' => 'open_source', 1, 'OpenSSL License' => 'unrestricted', 1, 'SSLeay License' => 'unrestricted', 1, 'zlib License' => 'open_source', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s#\s+#\\s+#gs; if ( $license_text =~ /\b$pattern\b/i ) { return $license; } } return ''; } sub license_from { my $self = shift; if (my $license=_extract_license(Module::Install::_read($_[0]))) { $self->license($license); } else { warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } } sub _extract_bugtracker { my @links = $_[0] =~ m#L<( https?\Q://rt.cpan.org/\E[^>]+| https?\Q://github.com/\E[\w_]+/[\w_]+/issues| https?\Q://code.google.com/p/\E[\w_\-]+/issues/list )>#gx; my %links; @links{@links}=(); @links=keys %links; return @links; } sub bugtracker_from { my $self = shift; my $content = Module::Install::_read($_[0]); my @links = _extract_bugtracker($content); unless ( @links ) { warn "Cannot determine bugtracker info from $_[0]\n"; return 0; } if ( @links > 1 ) { warn "Found more than one bugtracker link in $_[0]\n"; return 0; } # Set the bugtracker bugtracker( $links[0] ); return 1; } sub requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->requires( $module => $version ); } } sub test_requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->test_requires( $module => $version ); } } # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to # numbers (eg, 5.006001 or 5.008009). # Also, convert double-part versions (eg, 5.8) sub _perl_version { my $v = $_[-1]; $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e; $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e; $v =~ s/(\.\d\d\d)000$/$1/; $v =~ s/_.+$//; if ( ref($v) ) { # Numify $v = $v + 0; } return $v; } sub add_metadata { my $self = shift; my %hash = @_; for my $key (keys %hash) { warn "add_metadata: $key is not prefixed with 'x_'.\n" . "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/; $self->{values}->{$key} = $hash{$key}; } } ###################################################################### # MYMETA Support sub WriteMyMeta { die "WriteMyMeta has been deprecated"; } sub write_mymeta_yaml { my $self = shift; # We need YAML::Tiny to write the MYMETA.yml file unless ( eval { require YAML::Tiny; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.yml\n"; YAML::Tiny::DumpFile('MYMETA.yml', $meta); } sub write_mymeta_json { my $self = shift; # We need JSON to write the MYMETA.json file unless ( eval { require JSON; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.json\n"; Module::Install::_write( 'MYMETA.json', JSON->new->pretty(1)->canonical->encode($meta), ); } sub _write_mymeta_data { my $self = shift; # If there's no existing META.yml there is nothing we can do return undef unless -f 'META.yml'; # We need Parse::CPAN::Meta to load the file unless ( eval { require Parse::CPAN::Meta; 1; } ) { return undef; } # Merge the perl version into the dependencies my $val = $self->Meta->{values}; my $perl = delete $val->{perl_version}; if ( $perl ) { $val->{requires} ||= []; my $requires = $val->{requires}; # Canonize to three-dot version after Perl 5.6 if ( $perl >= 5.006 ) { $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e } unshift @$requires, [ perl => $perl ]; } # Load the advisory META.yml file my @yaml = Parse::CPAN::Meta::LoadFile('META.yml'); my $meta = $yaml[0]; # Overwrite the non-configure dependency hashs delete $meta->{requires}; delete $meta->{build_requires}; delete $meta->{recommends}; if ( exists $val->{requires} ) { $meta->{requires} = { map { @$_ } @{ $val->{requires} } }; } if ( exists $val->{build_requires} ) { $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } }; } return $meta; } 1; App-perlbrew-0.66/inc/Module/Install/Scripts.pm000644 000765 000024 00000001011 12177031265 021643 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Scripts; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub install_script { my $self = shift; my $args = $self->makemaker_args; my $exe = $args->{EXE_FILES} ||= []; foreach ( @_ ) { if ( -f $_ ) { push @$exe, $_; } elsif ( -d 'script' and -f "script/$_" ) { push @$exe, "script/$_"; } else { die("Cannot find script '$_'"); } } } 1; App-perlbrew-0.66/inc/Module/Install/Win32.pm000644 000765 000024 00000003403 12177031265 021125 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::Win32; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; App-perlbrew-0.66/inc/Module/Install/WriteAll.pm000644 000765 000024 00000002376 12177031265 021756 0ustar00gugodstaff000000 000000 #line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { # XXX: This still may be a bit over-defensive... unless ($self->makemaker(6.25)) { $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; } } # Until ExtUtils::MakeMaker support MYMETA.yml, make sure # we clean it up properly ourself. $self->realclean_files('MYMETA.yml'); if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } # The Makefile write process adds a couple of dependencies, # so write the META.yml files after the Makefile. if ( $args{meta} ) { $self->Meta->write; } # Experimental support for MYMETA if ( $ENV{X_MYMETA} ) { if ( $ENV{X_MYMETA} eq 'JSON' ) { $self->Meta->write_mymeta_json; } else { $self->Meta->write_mymeta_yaml; } } return 1; } 1; App-perlbrew-0.66/doc/MIT-LICENSE000644 000765 000024 00000002062 11534745500 016462 0ustar00gugodstaff000000 000000 The MIT License Copyright (c) 2010 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. App-perlbrew-0.66/doc/notes.org000644 000765 000024 00000002522 12176370331 016667 0ustar00gugodstaff000000 000000 # Here's some random notes about perlbrew that I take when I was thinking (or not.) * shell integration bashrc / cshrc should check if ~/.perlbrew/init before sourcing it. If ~/.perlbrew/init is missing, it is the same as perlbrew is not in effect. * info command $ perlbrew info perlbrew version 0.30 with bash integration PERLBREW_ROOT=... PERLBREW_HOME=... Disk Usage: 230MB $ perlbrew info perl-5.14.2 perl version 5.14.2, installed at $PERLBREW_ROOT/perls/perl-5.14.2 #Show the platform section of `perl -V` [x] Show the value of `Compiled at` from `perl -V` * When it is installed with cpan - `which perlbrew` is, most likely, not equal to "$PERLBREW_ROOT/bin/perlbrew" - Directories and files under $PERLBREW_ROOT/* might be absent * as a result, user need to go through a initialization process. to get $PERLBREW_ROOT ready - why ? can it be built on-the go ? - etc/bashrc and etc/cshrc makes it harder - When people run `perlbrew` for the very first time, perform `init` - When people run `perlbrew install 5.14.2` the very first time, perform `init` * When it is installed with the perlbrew installer * Black box testing Suppose: A fresh bash user. scripts to test the stand-alone `perlbrew` behaviour scripts to test the cpan-installed `perlbrew` behaviour App-perlbrew-0.66/doc/PERL-LICENSE000644 000765 000024 00000047371 11534745500 016607 0ustar00gugodstaff000000 000000 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 App-perlbrew-0.66/bin/perlbrew000755 000765 000024 00000044627 12176370331 016615 0ustar00gugodstaff000000 000000 #!/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. 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 enviroments. 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. mirror Pick a preferred mirror site 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 -kL 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. =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 Usage: perlbrew info The `info` command dumps a page of handful information for the perlbrew installation. =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. To configure mirror site, invoke `mirror` command. =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 -D,-U,-A Switches passed to perl Configure script. ex. C --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` =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 the installed versions of perl. =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 becomes 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: MIRROR Usage: perlbrew mirror Run this if you want to choose a specific CPAN mirror to install the perls from. It will display a list of mirrors for you to pick from. Hit 'q' to cancel the selection. =head1 COMMAND: EXEC Usage: perlbrew exec [--with perl-name[,perl-name...]] 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 use '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 install perlbrew itself to C<$PERLBREW_ROOT/bin>. It is intended used by the perlbrew installer. However, you may manually do the following to re-install only the C executable: curl -kL http://get.perlbrew.pl -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 downloaded Perl tarballs and build directories. =head1 COMMAND: VERSION Usage: perlbrew version Show the version of perlbrew. =head1 COMMAND: LIB Usage: 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 libs by name perlbrew lib create nobita perlbrew lib create perl-5.12.3@shizuka perlbrew list # See the list of use/switch targets. # Activate a lib in current shell. perlbrew use perl-5.12.3@nobita perlbrew use perl-5.14.2@nobita # Activate a lib as default. perlbrew switch perl-5.14.2@nobita # Delete the lib perlbrew lib delete nobita 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 =head1 UPGRADE NOTES If you are upgrading C from 0.16 or earlier versions to a recent one (0.40-ish), you should do these steps to adjust your perl installations afterwards (you might need to change the value of PERLBREW_ROOT): export PERLBREW_ROOT=${HOME}/perl5/perlbrew rm -f $PERLBREW_ROOT/perls/current rm -f `find $PERLBREW_ROOT/perls/bin -type l` perlbrew symlink-executables perlbrew init Following the instructions on screen to tweak your shell a bit. Then it should be good. =head1 SEE ALSO L, L, L =cut