The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 013
LICENSE 11
MANIFEST 01
META.json 35
META.yml 810
Makefile.PL 2413
bin/cpanm 6496
lib/App/cpanminus/fatscript.pm 8521843
lib/App/cpanminus.pm 11
9 files changed (This is a version diff) 9531983
@@ -1,5 +1,18 @@
 See http://github.com/miyagawa/cpanminus/ for the latest development.
 
+1.7004  2014-04-27 18:22:11 CEST
+   [Bug Fixes]
+      - Downgrade Parse::CPAN::Meta as well #373
+
+1.7003  2014-04-27 17:11:14 CEST
+   [Bug Fixes]
+      - Downgrade CPAN::Meta (moznion) #372
+
+1.7002  2014-04-27 07:45:53 CEST
+   [Bug Fixes]
+      - Bump fatpacked local::lib #364
+      - Fix a bug where build.log files are not properly renamed on the first run on Win32 (haarg) #368
+
 1.7001  2013-09-08 13:11:16 PDT
    [Bug Fixes]
       - Fix bootstrap with perl 5.8 and MakeMaker/Module::Build (haarg) #311
@@ -22,7 +22,7 @@ This is free software, licensed under:
                      Version 1, February 1989
 
  Copyright (C) 1989 Free Software Foundation, Inc.
- 51 Franklin St, Suite 500, Boston, MA  02110-1335  USA
+ 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.015.
 Changes
 LICENSE
 MANIFEST
@@ -4,7 +4,7 @@
       "- Tatsuhiko Miyagawa"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Milla version v1.0.4, Dist::Zilla version 4.300038, CPAN::Meta::Converter version 2.132510",
+   "generated_by" : "Dist::Milla version v1.0.4, Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640",
    "license" : [
       "perl_5"
    ],
@@ -101,7 +101,7 @@
          "web" : "https://github.com/miyagawa/cpanminus"
       }
    },
-   "version" : "1.7001",
+   "version" : "1.7004",
    "x_contributors" : [
       "Alessandro Ghedini <al3xbio@gmail.com>",
       "Andrew Rodland <andrew@cleverdomain.org>",
@@ -109,12 +109,13 @@
       "Ben Bullock <benkasminbullock@gmail.com>",
       "Breno G. de Oliveira <garu@cpan.org>",
       "Christian Walde <walde.christian@googlemail.com>",
-      "Dagfinn Ilmari Manns\u00e5ker <ilmari@ilmari.org>",
+      "Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>",
       "Dave Goodell <davidjgoodell@gmail.com>",
       "Dave Rolsky <autarch@urth.org>",
       "David Golden <dagolden@cpan.org>",
       "David Steinbrunner <dsteinbrunner@pobox.com>",
       "Fuji, Goro <g.psy.va@gmail.com>",
+      "Graham Knop <haarg@haarg.org>",
       "Ingy dot Net <ingy@ingy.net>",
       "J. Nick Koston <nick@cpanel.net>",
       "Jan Dubois <jand@activestate.com>",
@@ -155,6 +156,7 @@
       "kmx <kmx@cpan.org>",
       "lestrrat <lestrrat+github@gmail.com>",
       "motemen <motemen@gmail.com>",
+      "moznion <moznion@gmail.com>",
       "reezer <kind@gmx.at>",
       "robario <webmaster@robario.com>",
       "vti <viacheslav.t@gmail.com>",
@@ -3,15 +3,15 @@ abstract: 'get, unpack, build and install modules from CPAN'
 author:
   - '- Tatsuhiko Miyagawa'
 build_requires:
-  Test::More: 0
+  Test::More: '0'
 configure_requires:
-  ExtUtils::MakeMaker: 6.30
+  ExtUtils::MakeMaker: '6.30'
 dynamic_config: 0
-generated_by: 'Dist::Milla version v1.0.4, Dist::Zilla version 4.300038, CPAN::Meta::Converter version 2.132510'
+generated_by: 'Dist::Milla version v1.0.4, Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: App-cpanminus
 no_index:
   directory:
@@ -24,14 +24,14 @@ no_index:
   file:
     - lib/App/cpanminus/fatscript.pm
 requires:
-  ExtUtils::Install: 1.46
-  ExtUtils::MakeMaker: 6.31
-  Module::Build: 0.36
+  ExtUtils::Install: '1.46'
+  ExtUtils::MakeMaker: '6.31'
+  Module::Build: '0.36'
 resources:
   bugtracker: https://github.com/miyagawa/cpanminus/issues
   homepage: https://github.com/miyagawa/cpanminus
   repository: https://github.com/miyagawa/cpanminus.git
-version: 1.7001
+version: '1.7004'
 x_contributors:
   - 'Alessandro Ghedini <al3xbio@gmail.com>'
   - 'Andrew Rodland <andrew@cleverdomain.org>'
@@ -45,6 +45,7 @@ x_contributors:
   - 'David Golden <dagolden@cpan.org>'
   - 'David Steinbrunner <dsteinbrunner@pobox.com>'
   - 'Fuji, Goro <g.psy.va@gmail.com>'
+  - 'Graham Knop <haarg@haarg.org>'
   - 'Ingy dot Net <ingy@ingy.net>'
   - 'J. Nick Koston <nick@cpanel.net>'
   - 'Jan Dubois <jand@activestate.com>'
@@ -85,6 +86,7 @@ x_contributors:
   - 'kmx <kmx@cpan.org>'
   - 'lestrrat <lestrrat+github@gmail.com>'
   - 'motemen <motemen@gmail.com>'
+  - 'moznion <moznion@gmail.com>'
   - 'reezer <kind@gmx.at>'
   - 'robario <webmaster@robario.com>'
   - 'vti <viacheslav.t@gmail.com>'
@@ -1,4 +1,5 @@
 
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.015.
 use strict;
 use warnings;
 
@@ -29,37 +30,25 @@ my %WriteMakefileArgs = (
   "TEST_REQUIRES" => {
     "Test::More" => 0
   },
-  "VERSION" => "1.7001",
+  "VERSION" => "1.7004",
   "test" => {
     "TESTS" => "t/*.t"
   }
 );
 
 
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
-  my $tr = delete $WriteMakefileArgs{TEST_REQUIRES};
-  my $br = $WriteMakefileArgs{BUILD_REQUIRES};
-  for my $mod ( keys %$tr ) {
-    if ( exists $br->{$mod} ) {
-      $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
-    }
-    else {
-      $br->{$mod} = $tr->{$mod};
-    }
-  }
-}
+my %FallbackPrereqs = (
+  "ExtUtils::Install" => "1.46",
+  "ExtUtils::MakeMaker" => "6.31",
+  "Module::Build" => "0.36",
+  "Test::More" => 0
+);
 
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
-  my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
-  my $pp = $WriteMakefileArgs{PREREQ_PM};
-  for my $mod ( keys %$br ) {
-    if ( exists $pp->{$mod} ) {
-      $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
-    }
-    else {
-      $pp->{$mod} = $br->{$mod};
-    }
-  }
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+  delete $WriteMakefileArgs{TEST_REQUIRES};
+  delete $WriteMakefileArgs{BUILD_REQUIRES};
+  $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
 }
 
 delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
@@ -18,19 +18,19 @@ our $VERSION = "1.6928";
 BEGIN {
 my %fatpacked;
 
-$fatpacked{"App/cpanminus.pm"} = <<'APP_CPANMINUS';
-  package App::cpanminus;our$VERSION="1.7001";1;
+$fatpacked{"App/cpanminus.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS';
+  package App::cpanminus;our$VERSION="1.7004";1;
 APP_CPANMINUS
 
-$fatpacked{"App/cpanminus/CPANVersion.pm"} = <<'APP_CPANMINUS_CPANVERSION';
+$fatpacked{"App/cpanminus/CPANVersion.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_CPANVERSION';
   package App::cpanminus::CPANVersion;use strict;sub vcmp {my($self,$l,$r)=@_;local($^W)=0;return 0 if$l eq $r;for ($l,$r){s/_//g}for ($l,$r){next unless tr/.// > 1 || /^v/;s/^v?/v/;1 while s/\.0+(\d)/.$1/}if ($l=~/^v/ <=> $r=~/^v/){for ($l,$r){next if /^v/;$_=$self->float2vv($_)}}my$lvstring="v0";my$rvstring="v0";if ($] >= 5.006 && $l =~ /^v/ && $r =~ /^v/){$lvstring=$self->vstring($l);$rvstring=$self->vstring($r)}return (($l ne "undef")<=> ($r ne "undef")|| $lvstring cmp $rvstring || $l <=> $r || $l cmp $r)}sub vgt {my($self,$l,$r)=@_;$self->vcmp($l,$r)> 0}sub vlt {my($self,$l,$r)=@_;$self->vcmp($l,$r)< 0}sub vge {my($self,$l,$r)=@_;$self->vcmp($l,$r)>= 0}sub vle {my($self,$l,$r)=@_;$self->vcmp($l,$r)<= 0}sub vstring {my($self,$n)=@_;$n =~ s/^v// or die "CPAN::Version::vstring() called with invalid arg [$n]";pack "U*",split /\./,$n}sub float2vv {my($self,$n)=@_;my($rev)=int($n);$rev ||=0;my($mantissa)=$n =~ /\.(\d{1,12})/;$mantissa ||=0;$mantissa .= "0" while length($mantissa)%3;my$ret="v" .$rev;while ($mantissa){$mantissa =~ s/(\d{1,3})// or die "Panic: length>0 but not a digit? mantissa[$mantissa]";$ret .= ".".int($1)}$ret =~ s/(\.0)+/.0/;$ret}sub readable {my($self,$n)=@_;$n =~ /^([\w\-\+\.]+)/;return $1 if defined $1 && length($1)>0;if ($] < 5.006){warn("Suspicious version string seen [$n]\n");return$n}my$better=sprintf "v%vd",$n;return$better}1;
 APP_CPANMINUS_CPANVERSION
 
-$fatpacked{"App/cpanminus/Dependency.pm"} = <<'APP_CPANMINUS_DEPENDENCY';
+$fatpacked{"App/cpanminus/Dependency.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_DEPENDENCY';
   package App::cpanminus::Dependency;use strict;use CPAN::Meta::Requirements;sub from_prereqs {my($class,$prereq,$phases,$types)=@_;my@deps;for my$type (@$types){my$req=CPAN::Meta::Requirements->new;$req->add_requirements($prereq->requirements_for($_,$type))for @$phases;push@deps,$class->from_versions($req->as_string_hash,$type)}return@deps}sub from_versions {my($class,$versions,$type)=@_;my@deps;while (my($module,$version)=each %$versions){push@deps,$class->new($module,$version,$type)}@deps}sub new {my($class,$module,$version,$type)=@_;bless {module=>$module,version=>$version,type=>$type || 'requires',},$class}sub module {$_[0]->{module}}sub version {$_[0]->{version}}sub type {$_[0]->{type}}sub is_requirement {$_[0]->{type}eq 'requires'}1;
 APP_CPANMINUS_DEPENDENCY
 
-$fatpacked{"App/cpanminus/ParsePM.pm"} = <<'APP_CPANMINUS_PARSEPM';
+$fatpacked{"App/cpanminus/ParsePM.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_PARSEPM';
   package App::cpanminus::ParsePM;use strict;use warnings;use Safe;use JSON::PP;use Dumpvalue;use version ();use File::Spec ();use File::Temp ();use POSIX ':sys_wait_h';use App::cpanminus::CPANVersion;our$VERSION='0.04';our$VERBOSE=0;our$ALLOW_DEV_VERSION=0;sub new {my ($class,$meta)=@_;bless {META_CONTENT=>$meta},$class}sub parse {my ($self,$pmfile)=@_;$pmfile =~ s|\\|/|g;my($filemtime)=(stat$pmfile)[9];$self->{MTIME}=$filemtime;$self->{PMFILE}=$pmfile;unless ($self->_version_from_meta_ok){$self->{VERSION}=$self->_parse_version;if ($self->{VERSION}=~ /^\{.*\}$/){}elsif ($self->{VERSION}=~ /[_\s]/ &&!$ALLOW_DEV_VERSION){return}}my($ppp)=$self->_packages_per_pmfile;my@keys_ppp=$self->_filter_ppps(sort keys %$ppp);$self->_verbose(1,"Will check keys_ppp[@keys_ppp]\n");my ($package);DBPACK: foreach$package (@keys_ppp){if ($package !~ /^\w[\w\:\']*\w?\z/ || $package !~ /\w\z/ || $package =~ /:/ && $package !~ /::/ || $package =~ /\w:\w/ || $package =~ /:::/){$self->_verbose(1,"Package[$package] did not pass the ultimate sanity check");delete$ppp->{$package};next}my$pp=$ppp->{$package};if ($pp->{version}&& $pp->{version}=~ /^\{.*\}$/){my$err=JSON::PP::decode_json($pp->{version});if ($err->{openerr}){$self->_verbose(1,qq{Parse::PMFile was not able to
           read the file. It issued the following error: C< $err->{r} >},)}else {$self->_verbose(1,qq{Parse::PMFile was not able to
           parse the following line in that file: C< $err->{line} >
@@ -60,8 +60,8 @@ $fatpacked{"App/cpanminus/ParsePM.pm"} = <<'APP_CPANMINUS_PARSEPM';
         };local $^W=0;local$SIG{__WARN__}=sub {};$result=eval($eval);if ($@ or!defined$result){die +{eval=>$eval,line=>$current_parsed_line,file=>$parsefile,err=>$@,}}last}close FH;$result="undef" unless defined$result;return$result}}sub _filter_ppps {my($self,@ppps)=@_;my@res;MANI: for my$ppp (@ppps){if ($self->{META_CONTENT}){my$no_index=$self->{META_CONTENT}{no_index}|| $self->{META_CONTENT}{private};if (ref($no_index)eq 'HASH'){my%map=(package=>qr{\z},namespace=>qr{::},);for my$k (qw(package namespace)){next unless my$v=$no_index->{$k};my$rest=$map{$k};if (ref$v eq "ARRAY"){for my$ve (@$v){$ve =~ s|::$||;if ($ppp =~ /^$ve$rest/){$self->_verbose(1,"Skipping ppp[$ppp] due to ve[$ve]");next MANI}else {$self->_verbose(1,"NOT skipping ppp[$ppp] due to ve[$ve]")}}}else {$v =~ s|::$||;if ($ppp =~ /^$v$rest/){$self->_verbose(1,"Skipping ppp[$ppp] due to v[$v]");next MANI}else {$self->_verbose(1,"NOT skipping ppp[$ppp] due to v[$v]")}}}}else {$self->_verbose(1,"No keyword 'no_index' or 'private' in META_CONTENT")}}else {}push@res,$ppp}$self->_verbose(1,"Result of filter_ppps: res[@res]");@res}sub _simile {my($self,$file,$package)=@_;$file =~ s|.*/||;$file =~ s|\.pm(?:\.PL)?||;my$ret=$package =~ m/\b\Q$file\E$/;$ret ||=0;unless ($ret){$ret=1 if lc$file eq 'version'}$self->_verbose(1,"Result of simile(): file[$file] package[$package] ret[$ret]\n");$ret}sub _normalize_version {my($self,$v)=@_;$v="undef" unless defined$v;my$dv=Dumpvalue->new;my$sdv=$dv->stringify($v,1);$self->_verbose(1,"Result of normalize_version: sdv[$sdv]\n");return$v if$v eq "undef";return$v if$v =~ /^\{.*\}$/;$v =~ s/^\s+//;$v =~ s/\s+\z//;if ($v =~ /_/){return$v }my$vv=eval {no warnings;version->new($v)->numify};if ($@){return "undef"}if ($vv eq $v){}else {my$forced=$self->_force_numeric($v);if ($forced eq $vv){}elsif ($forced =~ /^v(.+)/){$vv=version->new($1)->numify}else {if ($forced==$vv){$vv=$forced}}}return$vv}sub _force_numeric {my($self,$v)=@_;$v=App::cpanminus::CPANVersion->readable($v);if ($v =~ /^(\+?)(\d*)(\.(\d*))?/ && (defined $2 && length $2 || defined $4 && length $4)){my$two=defined $2 ? $2 : "";my$three=defined $3 ? $3 : "";$v="$two$three"}$v}sub _version_from_meta_ok {my($self)=@_;return$self->{VERSION_FROM_META_OK}if exists$self->{VERSION_FROM_META_OK};my$c=$self->{META_CONTENT};return($self->{VERSION_FROM_META_OK}=0)unless$c->{provides};my ($mb_v)=(defined$c->{generated_by}? $c->{generated_by}: '')=~ /Module::Build version ([\d\.]+)/;return($self->{VERSION_FROM_META_OK}=1)unless$mb_v;return($self->{VERSION_FROM_META_OK}=1)if$mb_v eq '0.250.0';if ($mb_v >= 0.19 && $mb_v < 0.26 &&!keys %{$c->{provides}}){return($self->{VERSION_FROM_META_OK}=0)}return($self->{VERSION_FROM_META_OK}=1)}sub _verbose {my($self,$level,@what)=@_;warn@what if$level <= $VERBOSE}1;
 APP_CPANMINUS_PARSEPM
 
-$fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
-  package App::cpanminus::script;use strict;use Config;use Cwd ();use App::cpanminus;use File::Basename ();use File::Find ();use File::Path ();use File::Spec ();use File::Copy ();use File::Temp ();use Getopt::Long ();use Parse::CPAN::Meta;use Symbol ();use String::ShellQuote ();use version ();use aliased 'App::cpanminus::Dependency';use constant WIN32=>$^O eq 'MSWin32';use constant SUNOS=>$^O eq 'solaris';use constant CAN_SYMLINK=>eval {symlink("","");1};our$VERSION=$App::cpanminus::VERSION;if ($INC{"App/FatPacker/Trace.pm"}){require JSON::PP;require CPAN::Meta::YAML;require CPAN::Meta::Prereqs;require version::vpp;require File::pushd}my$quote=WIN32 ? q/"/ : q/'/;sub agent {my$self=shift;my$agent="cpanminus/$VERSION";$agent .= " perl/$]" if$self->{report_perl_version};$agent}sub determine_home {my$class=shift;my$homedir=$ENV{HOME}|| eval {require File::HomeDir;File::HomeDir->my_home}|| join('',@ENV{qw(HOMEDRIVE HOMEPATH)});if (WIN32){require Win32;$homedir=Win32::GetShortPathName($homedir)}return "$homedir/.cpanm"}sub new {my$class=shift;bless {home=>$class->determine_home,cmd=>'install',seen=>{},notest=>undef,test_only=>undef,installdeps=>undef,force=>undef,sudo=>undef,make=>undef,verbose=>undef,quiet=>undef,interactive=>undef,log=>undef,mirrors=>[],mirror_only=>undef,mirror_index=>undef,cpanmetadb=>"http://cpanmetadb.plackperl.org/v1.0/",perl=>$^X,argv=>[],local_lib=>undef,self_contained=>undef,prompt_timeout=>0,prompt=>undef,configure_timeout=>60,build_timeout=>3600,test_timeout=>1800,try_lwp=>1,try_wget=>1,try_curl=>1,uninstall_shadows=>($] < 5.012),skip_installed=>1,skip_satisfied=>0,auto_cleanup=>7,pod2man=>1,installed_dists=>0,install_types=>['requires'],with_develop=>0,showdeps=>0,scandeps=>0,scandeps_tree=>[],format=>'tree',save_dists=>undef,skip_configure=>0,verify=>0,report_perl_version=>1,build_args=>{},features=>{},pure_perl=>0,cpanfile_path=>'cpanfile',@_,},$class}sub env {my($self,$key)=@_;$ENV{"PERL_CPANM_" .$key}}sub install_type_handlers {my$self=shift;my@handlers;for my$type (qw(recommends suggests)){push@handlers,"with-$type"=>sub {my%uniq;$self->{install_types}=[grep!$uniq{$_}++,@{$self->{install_types}},$type ]};push@handlers,"without-$type"=>sub {$self->{install_types}=[grep $_ ne $type,@{$self->{install_types}}]}}@handlers}sub build_args_handlers {my$self=shift;my@handlers;for my$phase (qw(configure build test install)){push@handlers,"$phase-args=s"=>\($self->{build_args}{$phase})}@handlers}sub parse_options {my$self=shift;local@ARGV=@{$self->{argv}};push@ARGV,grep length,split /\s+/,$self->env('OPT');push@ARGV,@_;Getopt::Long::Configure("bundling");Getopt::Long::GetOptions('f|force'=>sub {$self->{skip_installed}=0;$self->{force}=1},'n|notest!'=>\$self->{notest},'test-only'=>sub {$self->{notest}=0;$self->{skip_installed}=0;$self->{test_only}=1},'S|sudo!'=>\$self->{sudo},'v|verbose'=>\$self->{verbose},'verify!'=>\$self->{verify},'q|quiet!'=>\$self->{quiet},'h|help'=>sub {$self->{action}='show_help'},'V|version'=>sub {$self->{action}='show_version'},'perl=s'=>\$self->{perl},'l|local-lib=s'=>sub {$self->{local_lib}=$self->maybe_abs($_[1])},'L|local-lib-contained=s'=>sub {$self->{local_lib}=$self->maybe_abs($_[1]);$self->{self_contained}=1;$self->{pod2man}=undef},'self-contained!'=>\$self->{self_contained},'mirror=s@'=>$self->{mirrors},'mirror-only!'=>\$self->{mirror_only},'mirror-index=s'=>\$self->{mirror_index},'cpanmetadb=s'=>\$self->{cpanmetadb},'cascade-search!'=>\$self->{cascade_search},'prompt!'=>\$self->{prompt},'installdeps'=>\$self->{installdeps},'skip-installed!'=>\$self->{skip_installed},'skip-satisfied!'=>\$self->{skip_satisfied},'reinstall'=>sub {$self->{skip_installed}=0},'interactive!'=>\$self->{interactive},'i|install'=>sub {$self->{cmd}='install'},'info'=>sub {$self->{cmd}='info'},'look'=>sub {$self->{cmd}='look';$self->{skip_installed}=0},'U|uninstall'=>sub {$self->{cmd}='uninstall'},'self-upgrade'=>sub {$self->{action}='self_upgrade'},'uninst-shadows!'=>\$self->{uninstall_shadows},'lwp!'=>\$self->{try_lwp},'wget!'=>\$self->{try_wget},'curl!'=>\$self->{try_curl},'auto-cleanup=s'=>\$self->{auto_cleanup},'man-pages!'=>\$self->{pod2man},'scandeps'=>\$self->{scandeps},'showdeps'=>sub {$self->{showdeps}=1;$self->{skip_installed}=0},'format=s'=>\$self->{format},'save-dists=s'=>sub {$self->{save_dists}=$self->maybe_abs($_[1])},'skip-configure!'=>\$self->{skip_configure},'dev!'=>\$self->{dev_release},'metacpan!'=>\$self->{metacpan},'report-perl-version!'=>\$self->{report_perl_version},'configure-timeout=i'=>\$self->{configure_timeout},'build-timeout=i'=>\$self->{build_timeout},'test-timeout=i'=>\$self->{test_timeout},'with-develop'=>\$self->{with_develop},'without-develop'=>sub {$self->{with_develop}=0},'with-feature=s'=>sub {$self->{features}{$_[1]}=1},'without-feature=s'=>sub {$self->{features}{$_[1]}=0},'with-all-features'=>sub {$self->{features}{__all}=1},'pp|pureperl!'=>\$self->{pure_perl},"cpanfile=s"=>\$self->{cpanfile_path},$self->install_type_handlers,$self->build_args_handlers,);if (!@ARGV && $0 ne '-' &&!-t STDIN){push@ARGV,$self->load_argv_from_fh(\*STDIN);$self->{load_from_stdin}=1}$self->{argv}=\@ARGV}sub check_upgrade {my$self=shift;my$install_base=$ENV{PERL_LOCAL_LIB_ROOT}? $self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}): $Config{installsitebin};if ($0 eq '-'){return}elsif ($0 !~ /^$install_base/){if ($0 =~ m!perlbrew/bin!){die <<DIE}else {die <<DIE}}}sub check_libs {my$self=shift;return if$self->{_checked}++;$self->bootstrap_local_lib;if (@{$self->{bootstrap_deps}|| []}){local$self->{notest}=1;local$self->{scandeps}=0;$self->install_deps(Cwd::cwd,0,@{$self->{bootstrap_deps}})}}sub setup_verify {my$self=shift;my$has_modules=eval {require Module::Signature;require Digest::SHA;1};$self->{cpansign}=$self->which('cpansign');unless ($has_modules && $self->{cpansign}){warn "WARNING: Module::Signature and Digest::SHA is required for distribution verifications.\n";$self->{verify}=0}}sub parse_module_args {my($self,$module)=@_;$module =~ s/^([A-Za-z0-9_:]+)@([v\d\._]+)$/$1~== $2/;if ($module =~ /\~[v\d\._,\!<>= ]+$/){return split /\~/,$module,2}else {return$module,undef}}sub _exit {my($self,$code)=@_;die App::cpanminus::CommandExit->new($code)}sub doit {my$self=shift;my$code;eval {$code=($self->_doit==0)};if (my$e=$@){if (ref$e eq 'App::cpanminus::CommandExit'){$code=$e->code}else {warn$e;$code=1}}return$code}sub _doit {my$self=shift;$self->setup_home;$self->init_tools;$self->setup_verify if$self->{verify};if (my$action=$self->{action}){$self->$action()and return 1}$self->show_help(1)unless @{$self->{argv}}or $self->{load_from_stdin};$self->configure_mirrors;my$cwd=Cwd::cwd;my@fail;for my$module (@{$self->{argv}}){if ($module =~ s/\.pm$//i){my ($volume,$dirs,$file)=File::Spec->splitpath($module);$module=join '::',grep {$_}File::Spec->splitdir($dirs),$file}($module,my$version)=$self->parse_module_args($module);$self->chdir($cwd);if ($self->{cmd}eq 'uninstall'){$self->uninstall_module($module)or push@fail,$module}else {$self->install_module($module,0,$version)or push@fail,$module}}if ($self->{base}&& $self->{auto_cleanup}){$self->cleanup_workdirs}if ($self->{installed_dists}){my$dists=$self->{installed_dists}> 1 ? "distributions" : "distribution";$self->diag("$self->{installed_dists} $dists installed\n",1)}if ($self->{scandeps}){$self->dump_scandeps()}$self->chdir($cwd);return!@fail}sub setup_home {my$self=shift;$self->{home}=$self->env('HOME')if$self->env('HOME');unless (_writable($self->{home})){die "Can't write to cpanm home '$self->{home}': You should fix it with chown/chmod first.\n"}$self->{base}="$self->{home}/work/" .time .".$$";File::Path::mkpath([$self->{base}],0,0777);$self->{log}=File::Spec->catfile($self->{base},"build.log");my$final_log="$self->{home}/build.log";{open my$out,">$self->{log}" or die "$self->{log}: $!"}if (CAN_SYMLINK){my$build_link="$self->{home}/latest-build";unlink$build_link;symlink$self->{base},$build_link;unlink$final_log;symlink$self->{log},$final_log}else {my$log=$self->{log};my$home=$self->{home};$self->{at_exit}=sub {my$self=shift;my$temp_log="$home/build.log." .time .".$$";File::Copy::copy($log,$temp_log)&& unlink($final_log)&& rename($temp_log,$final_log)}}$self->chat("cpanm (App::cpanminus) $VERSION on perl $] built for $Config{archname}\n" ."Work directory is $self->{base}\n")}sub package_index_for {my ($self,$mirror)=@_;return$self->source_for($mirror)."/02packages.details.txt"}sub generate_mirror_index {my ($self,$mirror)=@_;my$file=$self->package_index_for($mirror);my$gz_file=$file .'.gz';my$index_mtime=(stat$gz_file)[9];unless (-e $file && (stat$file)[9]>= $index_mtime){$self->chat("Uncompressing index file...\n");if (eval {require Compress::Zlib}){my$gz=Compress::Zlib::gzopen($gz_file,"rb")or do {$self->diag_fail("$Compress::Zlib::gzerrno opening compressed index");return};open my$fh,'>',$file or do {$self->diag_fail("$! opening uncompressed index for write");return};my$buffer;while (my$status=$gz->gzread($buffer)){if ($status < 0){$self->diag_fail($gz->gzerror ." reading compressed index");return}print$fh $buffer}}else {if (system("gunzip -c $gz_file > $file")){$self->diag_fail("Cannot uncompress -- please install gunzip or Compress::Zlib");return}}utime$index_mtime,$index_mtime,$file}return 1}sub search_mirror_index {my ($self,$mirror,$module,$version)=@_;$self->search_mirror_index_file($self->package_index_for($mirror),$module,$version)}sub search_mirror_index_file {my($self,$file,$module,$version)=@_;open my$fh,'<',$file or return;my$found;while (<$fh>){if (m!^\Q$module\E\s+([\w\.]+)\s+(\S*)!m){$found=$self->cpan_module($module,$2,$1);last}}return$found unless$self->{cascade_search};if ($found){if ($self->satisfy_version($module,$found->{module_version},$version)){return$found}else {$self->chat("Found $module $found->{module_version} which doesn't satisfy $version.\n")}}return}sub with_version_range {my($self,$version)=@_;defined($version)&& $version =~ /[<>=]/}sub encode_json {my($self,$data)=@_;require JSON::PP;my$json=JSON::PP::encode_json($data);$json =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;$json}sub version_to_query {my($self,$module,$version)=@_;require CPAN::Meta::Requirements;my$requirements=CPAN::Meta::Requirements->new;$requirements->add_string_requirement($module,$version || '0');my$req=$requirements->requirements_for_module($module);if ($req =~ s/^==\s*//){return {term=>{'module.version'=>$req },}}elsif ($req !~ /\s/){return {range=>{'module.version_numified'=>{'gte'=>$self->numify_ver($req)}},}}else {my%ops=qw(< lt <= lte > gt >= gte);my(%range,@exclusion);my@requirements=split /,\s*/,$req;for my$r (@requirements){if ($r =~ s/^([<>]=?)\s*//){$range{$ops{$1}}=$self->numify_ver($r)}elsif ($r =~ s/\!=\s*//){push@exclusion,$self->numify_ver($r)}}my@filters=({range=>{'module.version_numified'=>\%range }},);if (@exclusion){push@filters,{not=>{or=>[map {+{term=>{'module.version_numified'=>$self->numify_ver($_)}}}@exclusion ]},}}return@filters}}sub numify_ver {my($self,$ver)=@_;version->new($ver)->numify}sub maturity_filter {my($self,$module,$version)=@_;my@filters;if (!$self->with_version_range($version)or $self->{dev_release}){push@filters,{not=>{term=>{status=>'backpan' }}}}unless ($self->{dev_release}or $version =~ /==/){push@filters,{term=>{maturity=>'released' }}}return@filters}sub by_version {my%s=qw(latest 3 cpan 2 backpan 1);$b->{_score}<=> $a->{_score}|| $s{$b->{fields}{status}}<=> $s{$a->{fields}{status}}}sub by_first_come {$a->{fields}{date}cmp $b->{fields}{date}}sub by_date {$b->{fields}{date}cmp $a->{fields}{date}}sub find_best_match {my($self,$match,$version)=@_;return unless$match && @{$match->{hits}{hits}|| []};my@hits=$self->{dev_release}? sort {by_version || by_date}@{$match->{hits}{hits}}: sort {by_version || by_first_come}@{$match->{hits}{hits}};$hits[0]->{fields}}sub search_metacpan {my($self,$module,$version)=@_;require JSON::PP;$self->chat("Searching $module ($version) on metacpan ...\n");my$metacpan_uri='http://api.metacpan.org/v0';my@filter=$self->maturity_filter($module,$version);my$query={filtered=>{(@filter ? (filter=>{and=>\@filter }): ()),query=>{nested=>{score_mode=>'max',path=>'module',query=>{custom_score=>{metacpan_script=>"score_version_numified",query=>{constant_score=>{filter=>{and=>[{term=>{'module.authorized'=>JSON::PP::true()}},{term=>{'module.indexed'=>JSON::PP::true()}},{term=>{'module.name'=>$module }},$self->version_to_query($module,$version),]}}},}},}},}};my$module_uri="$metacpan_uri/file/_search?source=";$module_uri .= $self->encode_json({query=>$query,fields=>['date','release','module','status' ],});my($release,$module_version);my$module_json=$self->get($module_uri);my$module_meta=eval {JSON::PP::decode_json($module_json)};my$match=$self->find_best_match($module_meta);if ($match){$release=$match->{release};my$module_matched=(grep {$_->{name}eq $module}@{$match->{module}})[0];$module_version=$module_matched->{version}}unless ($release){$self->chat("! Could not find a release matching $module ($version) on MetaCPAN.\n");return}my$dist_uri="$metacpan_uri/release/_search?source=";$dist_uri .= $self->encode_json({filter=>{term=>{'release.name'=>$release },},fields=>['download_url','stat','status' ],});my$dist_json=$self->get($dist_uri);my$dist_meta=eval {JSON::PP::decode_json($dist_json)};if ($dist_meta){$dist_meta=$dist_meta->{hits}{hits}[0]{fields}}if ($dist_meta && $dist_meta->{download_url}){(my$distfile=$dist_meta->{download_url})=~ s!.+/authors/id/!!;local$self->{mirrors}=$self->{mirrors};if ($dist_meta->{status}eq 'backpan'){$self->{mirrors}=['http://backpan.perl.org' ]}elsif ($dist_meta->{stat}{mtime}> time()-24*60*60){$self->{mirrors}=['http://cpan.metacpan.org' ]}return$self->cpan_module($module,$distfile,$module_version)}$self->diag_fail("Finding $module on metacpan failed.");return}sub search_database {my($self,$module,$version)=@_;my$found;my$range=($self->with_version_range($version)|| $self->{dev_release});if ($range or $self->{metacpan}){$found=$self->search_metacpan($module,$version)and return$found;$found=$self->search_cpanmetadb($module,$version)and return$found}else {$found=$self->search_cpanmetadb($module,$version)and return$found;$found=$self->search_metacpan($module,$version)and return$found}}sub search_cpanmetadb {my($self,$module,$version)=@_;$self->chat("Searching $module on cpanmetadb ...\n");(my$uri=$self->{cpanmetadb})=~ s{/?$}{/package/$module};my$yaml=$self->get($uri);my$meta=$self->parse_meta_string($yaml);if ($meta && $meta->{distfile}){return$self->cpan_module($module,$meta->{distfile},$meta->{version})}$self->diag_fail("Finding $module on cpanmetadb failed.");return}sub search_module {my($self,$module,$version)=@_;if ($self->{mirror_index}){$self->mask_output(chat=>"Searching $module on mirror index $self->{mirror_index} ...\n");my$pkg=$self->search_mirror_index_file($self->{mirror_index},$module,$version);return$pkg if$pkg;unless ($self->{cascade_search}){$self->mask_output(diag_fail=>"Finding $module ($version) on mirror index $self->{mirror_index} failed.");return}}unless ($self->{mirror_only}){my$found=$self->search_database($module,$version);return$found if$found}MIRROR: for my$mirror (@{$self->{mirrors}}){$self->mask_output(chat=>"Searching $module on mirror $mirror ...\n");my$name='02packages.details.txt.gz';my$uri="$mirror/modules/$name";my$gz_file=$self->package_index_for($mirror).'.gz';unless ($self->{pkgs}{$uri}){$self->mask_output(chat=>"Downloading index file $uri ...\n");$self->mirror($uri,$gz_file);$self->generate_mirror_index($mirror)or next MIRROR;$self->{pkgs}{$uri}="!!retrieved!!"}my$pkg=$self->search_mirror_index($mirror,$module,$version);return$pkg if$pkg;$self->mask_output(diag_fail=>"Finding $module ($version) on mirror $mirror failed.")}return}sub source_for {my($self,$mirror)=@_;$mirror =~ s/[^\w\.\-]+/%/g;my$dir="$self->{home}/sources/$mirror";File::Path::mkpath([$dir ],0,0777);return$dir}sub load_argv_from_fh {my($self,$fh)=@_;my@argv;while(defined(my$line=<$fh>)){chomp$line;$line =~ s/#.+$//;$line =~ s/^\s+//;$line =~ s/\s+$//;push@argv,split ' ',$line if$line}return@argv}sub show_version {my$self=shift;print "cpanm (App::cpanminus) version $VERSION ($0)\n";print "perl version $] ($^X)\n\n";print "  \%Config:\n";for my$key (qw(archname installsitelib installsitebin installman1dir installman3dir sitelibexp archlibexp privlibexp)){print "    $key=$Config{$key}\n"}print "  \%ENV:\n";for my$key (grep /^PERL/,sort keys%ENV){print "    $key=$ENV{$key}\n"}print "  \@INC:\n";for my$inc (@INC){print "    $inc\n" unless ref($inc)eq 'CODE'}return 1}sub show_help {my$self=shift;if ($_[0]){print <<USAGE;$self->_exit(1)}print <<HELP;return 1}sub _writable {my$dir=shift;my@dir=File::Spec->splitdir($dir);while (@dir){$dir=File::Spec->catdir(@dir);if (-e $dir){return -w _}pop@dir}return}sub maybe_abs {my($self,$lib)=@_;if ($lib eq '_' or $lib =~ /^~/ or File::Spec->file_name_is_absolute($lib)){return$lib}else {return File::Spec->canonpath(File::Spec->catdir(Cwd::cwd(),$lib))}}sub local_lib_target {my($self,$root)=@_;(grep {$_ ne ''}split /\Q$Config{path_sep}/,$root)[-1]}sub bootstrap_local_lib {my$self=shift;if ($self->{local_lib}){return$self->setup_local_lib($self->{local_lib})}if ($ENV{PERL_LOCAL_LIB_ROOT}&& $ENV{PERL_MM_OPT}){return$self->setup_local_lib($self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}),1)}return if$self->{sudo}or (_writable($Config{installsitelib})and _writable($Config{installsitebin}));if ($ENV{PERL_MM_OPT}and ($ENV{MODULEBUILDRC}or $ENV{PERL_MB_OPT})){$self->bootstrap_local_lib_deps;return}$self->setup_local_lib;$self->diag(<<DIAG,1);sleep 2}sub _core_only_inc {my($self,$base)=@_;require local::lib;(local::lib->resolve_path(local::lib->install_base_perl_path($base)),local::lib->resolve_path(local::lib->install_base_arch_path($base)),@Config{qw(privlibexp archlibexp)},)}sub _diff {my($self,$old,$new)=@_;my@diff;my%old=map {$_=>1}@$old;for my$n (@$new){push@diff,$n unless exists$old{$n}}@diff}sub _setup_local_lib_env {my($self,$base)=@_;$self->diag(<<WARN,1)if$base =~ /\s/;local$SIG{__WARN__}=sub {};local::lib->setup_env_hash_for($base,0)}sub setup_local_lib {my($self,$base,$no_env)=@_;$base=undef if$base eq '_';require local::lib;{local $0='cpanm';$base ||="~/perl5";$base=local::lib->resolve_path($base);if ($self->{self_contained}){my@inc=$self->_core_only_inc($base);$self->{search_inc}=[@inc ]}else {$self->{search_inc}=[local::lib->install_base_arch_path($base),local::lib->install_base_perl_path($base),@INC,]}$self->_setup_local_lib_env($base)unless$no_env;$self->{local_lib}=$base}$self->bootstrap_local_lib_deps}sub bootstrap_local_lib_deps {my$self=shift;push @{$self->{bootstrap_deps}},Dependency->new('ExtUtils::MakeMaker'=>6.31),Dependency->new('ExtUtils::Install'=>1.46)}sub prompt_bool {my($self,$mess,$def)=@_;my$val=$self->prompt($mess,$def);return lc$val eq 'y'}sub prompt {my($self,$mess,$def)=@_;my$isa_tty=-t STDIN && (-t STDOUT ||!(-f STDOUT || -c STDOUT));my$dispdef=defined$def ? "[$def] " : " ";$def=defined$def ? $def : "";if (!$self->{prompt}|| (!$isa_tty && eof STDIN)){return$def}local $|=1;local $\;my$ans;eval {local$SIG{ALRM}=sub {undef$ans;die "alarm\n"};print STDOUT "$mess $dispdef";alarm$self->{prompt_timeout}if$self->{prompt_timeout};$ans=<STDIN>;alarm 0};if (defined$ans){chomp$ans}else {print STDOUT "\n"}return (!defined$ans || $ans eq '')? $def : $ans}sub diag_ok {my($self,$msg)=@_;chomp$msg;$msg ||="OK";if ($self->{in_progress}){$self->_diag("$msg\n");$self->{in_progress}=0}$self->log("-> $msg\n")}sub diag_fail {my($self,$msg,$always)=@_;chomp$msg;if ($self->{in_progress}){$self->_diag("FAIL\n");$self->{in_progress}=0}if ($msg){$self->_diag("! $msg\n",$always,1);$self->log("-> FAIL $msg\n")}}sub diag_progress {my($self,$msg)=@_;chomp$msg;$self->{in_progress}=1;$self->_diag("$msg ... ");$self->log("$msg\n")}sub _diag {my($self,$msg,$always,$error)=@_;my$fh=$error ? *STDERR : *STDOUT;print {$fh}$msg if$always or $self->{verbose}or!$self->{quiet}}sub diag {my($self,$msg,$always)=@_;$self->_diag($msg,$always);$self->log($msg)}sub chat {my$self=shift;print STDERR @_ if$self->{verbose};$self->log(@_)}sub mask_output {my$self=shift;my$method=shift;$self->$method($self->mask_uri_passwords(@_))}sub log {my$self=shift;open my$out,">>$self->{log}";print$out @_}sub run {my($self,$cmd)=@_;if (WIN32){$cmd=$self->shell_quote(@$cmd)if ref$cmd eq 'ARRAY';unless ($self->{verbose}){$cmd .= " >> " .$self->shell_quote($self->{log})." 2>&1"}!system$cmd}else {my$pid=fork;if ($pid){waitpid$pid,0;return!$?}else {$self->run_exec($cmd)}}}sub run_exec {my($self,$cmd)=@_;if (ref$cmd eq 'ARRAY'){unless ($self->{verbose}){open my$logfh,">>",$self->{log};open STDERR,'>&',$logfh;open STDOUT,'>&',$logfh;close$logfh}exec @$cmd}else {unless ($self->{verbose}){$cmd .= " >> " .$self->shell_quote($self->{log})." 2>&1"}exec$cmd}}sub run_timeout {my($self,$cmd,$timeout)=@_;return$self->run($cmd)if WIN32 || $self->{verbose}||!$timeout;my$pid=fork;if ($pid){eval {local$SIG{ALRM}=sub {die "alarm\n"};alarm$timeout;waitpid$pid,0;alarm 0};if ($@ && $@ eq "alarm\n"){$self->diag_fail("Timed out (> ${timeout}s). Use --verbose to retry.");local$SIG{TERM}='IGNORE';kill TERM=>0;waitpid$pid,0;return}return!$?}elsif ($pid==0){$self->run_exec($cmd)}else {$self->chat("! fork failed: falling back to system()\n");$self->run($cmd)}}sub append_args {my($self,$cmd,$phase)=@_;if (my$args=$self->{build_args}{$phase}){$cmd=join ' ',$self->shell_quote(@$cmd),$args}$cmd}sub configure {my($self,$cmd,$depth)=@_;local$ENV{PERL5_CPAN_IS_RUNNING}=local$ENV{PERL5_CPANPLUS_IS_RUNNING}=$$;local$ENV{PERL5_CPANM_IS_RUNNING}=$$;my$use_default=!$self->{interactive};local$ENV{PERL_MM_USE_DEFAULT}=$use_default;local$ENV{PERL_MM_OPT}=$ENV{PERL_MM_OPT};local$ENV{PERL_MB_OPT}=$ENV{PERL_MB_OPT};unless ($self->{pod2man}){$ENV{PERL_MM_OPT}.= " INSTALLMAN1DIR=none INSTALLMAN3DIR=none";$ENV{PERL_MB_OPT}.= " --config installman1dir= --config installsiteman1dir= --config installman3dir= --config installsiteman3dir="}if ($self->{pure_perl}){$ENV{PERL_MM_OPT}.= " PUREPERL_ONLY=1";$ENV{PERL_MB_OPT}.= " --pureperl-only"}$cmd=$self->append_args($cmd,'configure')if$depth==0;local$self->{verbose}=$self->{verbose}|| $self->{interactive};$self->run_timeout($cmd,$self->{configure_timeout})}sub build {my($self,$cmd,$distname,$depth)=@_;local$ENV{PERL_MM_USE_DEFAULT}=!$self->{interactive};$cmd=$self->append_args($cmd,'build')if$depth==0;return 1 if$self->run_timeout($cmd,$self->{build_timeout});while (1){my$ans=lc$self->prompt("Building $distname failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?","s");return if$ans eq 's';return$self->build($cmd,$distname,$depth)if$ans eq 'r';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}sub test {my($self,$cmd,$distname,$depth)=@_;return 1 if$self->{notest};local$ENV{PERL_MM_USE_DEFAULT}=!$self->{interactive};local$ENV{NONINTERACTIVE_TESTING}=!$self->{interactive};$cmd=$self->append_args($cmd,'test')if$depth==0;return 1 if$self->run_timeout($cmd,$self->{test_timeout});if ($self->{force}){$self->diag_fail("Testing $distname failed but installing it anyway.");return 1}else {$self->diag_fail;while (1){my$ans=lc$self->prompt("Testing $distname failed.\nYou can s)kip, r)etry, f)orce install, e)xamine build log, or l)ook ?","s");return if$ans eq 's';return$self->test($cmd,$distname,$depth)if$ans eq 'r';return 1 if$ans eq 'f';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}}sub install {my($self,$cmd,$uninst_opts,$depth)=@_;if ($depth==0 && $self->{test_only}){return 1}if ($self->{sudo}){unshift @$cmd,"sudo"}if ($self->{uninstall_shadows}&&!$ENV{PERL_MM_OPT}){push @$cmd,@$uninst_opts}$cmd=$self->append_args($cmd,'install')if$depth==0;$self->run($cmd)}sub look {my$self=shift;my$shell=$ENV{SHELL};$shell ||=$ENV{COMSPEC}if WIN32;if ($shell){my$cwd=Cwd::cwd;$self->diag("Entering $cwd with $shell\n");system$shell}else {$self->diag_fail("You don't seem to have a SHELL :/")}}sub show_build_log {my$self=shift;my@pagers=($ENV{PAGER},(WIN32 ? (): ('less')),'more');my$pager;while (@pagers){$pager=shift@pagers;next unless$pager;$pager=$self->which($pager);next unless$pager;last}if ($pager){system("$pager < $self->{log}")}else {$self->diag_fail("You don't seem to have a PAGER :/")}}sub chdir {my$self=shift;Cwd::chdir(File::Spec->canonpath($_[0]))or die "$_[0]: $!"}sub configure_mirrors {my$self=shift;unless (@{$self->{mirrors}}){$self->{mirrors}=['http://www.cpan.org' ]}for (@{$self->{mirrors}}){s!^/!file:///!;s!/$!!}}sub self_upgrade {my$self=shift;$self->check_upgrade;$self->{argv}=['App::cpanminus' ];return}sub install_module {my($self,$module,$depth,$version)=@_;$self->check_libs;if ($self->{seen}{$module}++){$self->chat("Already tried $module. Skipping.\n");return 1}if ($self->{skip_satisfied}){my($ok,$local)=$self->check_module($module,$version || 0);if ($ok){$self->diag("You have $module ($local)\n",1);return 1}}my$dist=$self->resolve_name($module,$version);unless ($dist){my$what=$module .($version ? " ($version)" : "");$self->diag_fail("Couldn't find module or a distribution $what",1);return}if ($dist->{distvname}&& $self->{seen}{$dist->{distvname}}++){$self->chat("Already tried $dist->{distvname}. Skipping.\n");return 1}if ($self->{cmd}eq 'info'){print$self->format_dist($dist),"\n";return 1}$dist->{depth}=$depth;if ($dist->{module}){unless ($self->satisfy_version($dist->{module},$dist->{module_version},$version)){$self->diag("Found $dist->{module} $dist->{module_version} which doesn't satisfy $version.\n",1);return}my$cmp=$version ? "==" : "";my$requirement=$dist->{module_version}? "$cmp$dist->{module_version}" : 0;my($ok,$local)=$self->check_module($dist->{module},$requirement);if ($self->{skip_installed}&& $ok){$self->diag("$dist->{module} is up to date. ($local)\n",1);return 1}}if ($dist->{dist}eq 'perl'){$self->diag("skipping $dist->{pathname}\n");return 1}$self->diag("--> Working on $module\n");$dist->{dir}||=$self->fetch_module($dist);unless ($dist->{dir}){$self->diag_fail("Failed to fetch distribution $dist->{distvname}",1);return}$self->chat("Entering $dist->{dir}\n");$self->chdir($self->{base});$self->chdir($dist->{dir});if ($self->{cmd}eq 'look'){$self->look;return 1}return$self->build_stuff($module,$dist,$depth)}sub uninstall_search_path {my$self=shift;$self->{local_lib}? (local::lib->install_base_arch_path($self->{local_lib}),local::lib->install_base_perl_path($self->{local_lib})): @Config{qw(installsitearch installsitelib)}}sub uninstall_module {my ($self,$module)=@_;$self->check_libs;my@inc=$self->uninstall_search_path;my($metadata,$packlist)=$self->packlists_containing($module,\@inc);unless ($packlist){$self->diag_fail(<<DIAG,1);return}my@uninst_files=$self->uninstall_target($metadata,$packlist);$self->ask_permission($module,\@uninst_files)or return;$self->uninstall_files(@uninst_files,$packlist);$self->diag("Successfully uninstalled $module\n",1);return 1}sub packlists_containing {my($self,$module,$inc)=@_;require Module::Metadata;my$metadata=Module::Metadata->new_from_module($module,inc=>$inc)or return;my$packlist;my$wanted=sub {return unless $_ eq '.packlist' && -f $_;for my$file ($self->unpack_packlist($File::Find::name)){$packlist ||=$File::Find::name if$file eq $metadata->filename}};{require File::pushd;my$pushd=File::pushd::pushd();my@search=grep -d $_,map File::Spec->catdir($_,'auto'),@$inc;File::Find::find($wanted,@search)}return$metadata,$packlist}sub uninstall_target {my($self,$metadata,$packlist)=@_;if ($self->has_shadow_install($metadata)or $self->{local_lib}){grep$self->should_unlink($_),$self->unpack_packlist($packlist)}else {$self->unpack_packlist($packlist)}}sub has_shadow_install {my($self,$metadata)=@_;my@shadow=grep defined,map Module::Metadata->new_from_module($metadata->name,inc=>[$_]),@INC;@shadow >= 2}sub should_unlink {my($self,$file)=@_;if ($self->{local_lib}){$file =~ /^\Q$self->{local_lib}\E/}else {!(grep$file =~ /^\Q$_\E/,@Config{qw(installbin installscript installman1dir installman3dir)})}}sub ask_permission {my ($self,$module,$files)=@_;$self->diag("$module contains the following files:\n\n");for my$file (@$files){$self->diag("  $file\n")}$self->diag("\n");return 'force uninstall' if$self->{force};local$self->{prompt}=1;return$self->prompt_bool("Are you sure you want to uninstall $module?",'y')}sub unpack_packlist {my ($self,$packlist)=@_;open my$fh,'<',$packlist or die "$packlist: $!";map {chomp;$_}<$fh>}sub uninstall_files {my ($self,@files)=@_;$self->diag("\n");for my$file (@files){$self->diag("Unlink: $file\n");unlink$file or $self->diag_fail("$!: $file")}$self->diag("\n");return 1}sub format_dist {my($self,$dist)=@_;return "$dist->{cpanid}/$dist->{filename}"}sub trim {local $_=shift;tr/\n/ /d;s/^\s*|\s*$//g;$_}sub fetch_module {my($self,$dist)=@_;$self->chdir($self->{base});for my$uri (@{$dist->{uris}}){$self->mask_output(diag_progress=>"Fetching $uri");my$filename=$dist->{filename}|| $uri;my$name=File::Basename::basename($filename);my$cancelled;my$fetch=sub {my$file;eval {local$SIG{INT}=sub {$cancelled=1;die "SIGINT\n"};$self->mirror($uri,$name);$file=$name if -e $name};$self->diag("ERROR: " .trim("$@")."\n",1)if $@ && $@ ne "SIGINT\n";return$file};my($try,$file);while ($try++ < 3){$file=$fetch->();last if$cancelled or $file;$self->diag_fail("Download $uri failed. Retrying ... ")}if ($cancelled){$self->diag_fail("Download cancelled.");return}unless ($file){$self->diag_fail("Failed to download $uri");next}$self->diag_ok;$dist->{local_path}=File::Spec->rel2abs($name);my$dir=$self->unpack($file,$uri,$dist);next unless$dir;if (my$save=$self->{save_dists}){my$path=$dist->{pathname}? "$save/authors/id/$dist->{pathname}" : "$save/vendor/$file";$self->chat("Copying $name to $path\n");File::Path::mkpath([File::Basename::dirname($path)],0,0777);File::Copy::copy($file,$path)or warn $!}return$dist,$dir}}sub unpack {my($self,$file,$uri,$dist)=@_;if ($self->{verify}){$self->verify_archive($file,$uri,$dist)or return}$self->chat("Unpacking $file\n");my$dir=$file =~ /\.zip/i ? $self->unzip($file): $self->untar($file);unless ($dir){$self->diag_fail("Failed to unpack $file: no directory")}return$dir}sub verify_checksums_signature {my($self,$chk_file)=@_;require Module::Signature;$self->chat("Verifying the signature of CHECKSUMS\n");my$rv=eval {local$SIG{__WARN__}=sub {};my$v=Module::Signature::_verify($chk_file);$v==Module::Signature::SIGNATURE_OK()};if ($rv){$self->chat("Verified OK!\n")}else {$self->diag_fail("Verifying CHECKSUMS signature failed: $rv\n");return}return 1}sub verify_archive {my($self,$file,$uri,$dist)=@_;unless ($dist->{cpanid}){$self->chat("Archive '$file' does not seem to be from PAUSE. Skip verification.\n")}(my$mirror=$uri)=~ s!/authors/id.*$!!;(my$chksum_uri=$uri)=~ s!/[^/]*$!/CHECKSUMS!;my$chk_file=$self->source_for($mirror)."/$dist->{cpanid}.CHECKSUMS";$self->mask_output(diag_progress=>"Fetching $chksum_uri");$self->mirror($chksum_uri,$chk_file);unless (-e $chk_file){$self->diag_fail("Fetching $chksum_uri failed.\n");return}$self->diag_ok;$self->verify_checksums_signature($chk_file)or return;$self->verify_checksum($file,$chk_file)}sub verify_checksum {my($self,$file,$chk_file)=@_;$self->chat("Verifying the SHA1 for $file\n");open my$fh,"<$chk_file" or die "$chk_file: $!";my$data=join '',<$fh>;$data =~ s/\015?\012/\n/g;require Safe;my$chksum=Safe->new->reval($data);if (!ref$chksum or ref$chksum ne 'HASH'){$self->diag_fail("! Checksum file downloaded from $chk_file is broken.\n");return}if (my$sha=$chksum->{$file}{sha256}){my$hex=$self->sha1_for($file);if ($hex eq $sha){$self->chat("Checksum for $file: Verified!\n")}else {$self->diag_fail("Checksum mismatch for $file\n");return}}else {$self->chat("Checksum for $file not found in CHECKSUMS.\n");return}}sub sha1_for {my($self,$file)=@_;require Digest::SHA;open my$fh,"<",$file or die "$file: $!";my$dg=Digest::SHA->new(256);my($data);while (read($fh,$data,4096)){$dg->add($data)}return$dg->hexdigest}sub verify_signature {my($self,$dist)=@_;$self->diag_progress("Verifying the SIGNATURE file");my$out=`$self->{cpansign} -v --skip 2>&1`;$self->log($out);if ($out =~ /Signature verified OK/){$self->diag_ok("Verified OK");return 1}else {$self->diag_fail("SIGNATURE verificaion for $dist->{filename} failed\n");return}}sub resolve_name {my($self,$module,$version)=@_;if ($module =~ /^(ftp|https?|file):/){if ($module =~ m!authors/id/(.*)!){return$self->cpan_dist($1,$module)}else {return {uris=>[$module ]}}}if ($module =~ m!^[\./]! && -d $module){return {source=>'local',dir=>Cwd::abs_path($module),}}if (-f $module){return {source=>'local',uris=>["file://" .Cwd::abs_path($module)],}}if ($module =~ /(?:^git:|\.git(?:@.+)?$)/){return$self->git_uri($module)}if ($module =~ s!^cpan:///distfile/!!){return$self->cpan_dist($module)}if ($module =~ m!^(?:[A-Z]/[A-Z]{2}/)?([A-Z]{2}[\-A-Z0-9]*/.*)$!){return$self->cpan_dist($1)}return$self->search_module($module,$version)}sub cpan_module {my($self,$module,$dist,$version)=@_;my$dist=$self->cpan_dist($dist);$dist->{module}=$module;$dist->{module_version}=$version if$version && $version ne 'undef';return$dist}sub cpan_dist {my($self,$dist,$url)=@_;$dist =~ s!^([A-Z]{2})!substr($1,0,1)."/".substr($1,0,2)."/".$1!e;require CPAN::DistnameInfo;my$d=CPAN::DistnameInfo->new($dist);if ($url){$url=[$url ]unless ref$url eq 'ARRAY'}else {my$id=$d->cpanid;my$fn=substr($id,0,1)."/" .substr($id,0,2)."/" .$id ."/" .$d->filename;my@mirrors=@{$self->{mirrors}};my@urls=map "$_/authors/id/$fn",@mirrors;$url=\@urls,}return {$d->properties,source=>'cpan',uris=>$url,}}sub git_uri {my ($self,$uri)=@_;($uri,my$commitish)=split /(?<=\.git)@/i,$uri,2;my$dir=File::Temp::tempdir(CLEANUP=>1);$self->mask_output(diag_progress=>"Cloning $uri");$self->run(['git','clone',$uri,$dir ]);unless (-e "$dir/.git"){$self->diag_fail("Failed cloning git repository $uri",1);return}if ($commitish){require File::pushd;my$dir=File::pushd::pushd($dir);unless ($self->run(['git','checkout',$commitish ])){$self->diag_fail("Failed to checkout '$commitish' in git repository $uri\n");return}}$self->diag_ok;return {source=>'local',dir=>$dir,}}sub setup_module_build_patch {my$self=shift;open my$out,">$self->{base}/ModuleBuildSkipMan.pm" or die $!;print$out <<EOF}sub core_version_for {my($self,$module)=@_;require Module::CoreList;unless (exists$Module::CoreList::version{$]+0}){die sprintf("Module::CoreList %s (loaded from %s) doesn't seem to have entries for perl $]. " ."You're strongly recommended to upgrade Module::CoreList from CPAN.\n",$Module::CoreList::VERSION,$INC{"Module/CoreList.pm"})}unless (exists$Module::CoreList::version{$]+0}{$module}){return -1}return$Module::CoreList::version{$]+0}{$module}}sub check_module {my($self,$mod,$want_ver)=@_;require Module::Metadata;my$meta=Module::Metadata->new_from_module($mod,inc=>$self->{search_inc})or return 0,undef;my$version=$meta->version;if ($self->{self_contained}&& $self->loaded_from_perl_lib($meta)){$version=$self->core_version_for($mod);return 0,undef if$version && $version==-1}$self->{local_versions}{$mod}=$version;if ($self->is_deprecated($meta)){return 0,$version}elsif ($self->satisfy_version($mod,$version,$want_ver)){return 1,($version || 'undef')}else {return 0,$version}}sub satisfy_version {my($self,$mod,$version,$want_ver)=@_;$want_ver='0' unless defined($want_ver)&& length($want_ver);require CPAN::Meta::Requirements;my$requirements=CPAN::Meta::Requirements->new;$requirements->add_string_requirement($mod,$want_ver);$requirements->accepts_module($mod,$version)}sub unsatisfy_how {my($self,$ver,$want_ver)=@_;if ($want_ver =~ /^[v0-9\.\_]+$/){return "$ver < $want_ver"}else {return "$ver doesn't satisfy $want_ver"}}sub is_deprecated {my($self,$meta)=@_;my$deprecated=eval {require Module::CoreList;Module::CoreList::is_deprecated($meta->{module})};return$deprecated && $self->loaded_from_perl_lib($meta)}sub loaded_from_perl_lib {my($self,$meta)=@_;require Config;for my$dir (qw(archlibexp privlibexp)){my$confdir=$Config{$dir};if ($confdir eq substr($meta->filename,0,length($confdir))){return 1}}return}sub should_install {my($self,$mod,$ver)=@_;$self->chat("Checking if you have $mod $ver ... ");my($ok,$local)=$self->check_module($mod,$ver);if ($ok){$self->chat("Yes ($local)\n")}elsif ($local){$self->chat("No (" .$self->unsatisfy_how($local,$ver).")\n")}else {$self->chat("No\n")}return$mod unless$ok;return}sub check_perl_version {my($self,$version)=@_;require CPAN::Meta::Requirements;my$req=CPAN::Meta::Requirements->from_string_hash({perl=>$version });$req->accepts_module(perl=>$])}sub install_deps {my($self,$dir,$depth,@deps)=@_;my(@install,%seen,@fail);for my$dep (@deps){next if$seen{$dep->module};if ($dep->module eq 'perl'){if ($dep->is_requirement &&!$self->check_perl_version($dep->version)){$self->diag("Needs perl @{[$dep->version]}, you have $]\n");push@fail,'perl'}}elsif ($self->should_install($dep->module,$dep->version)){push@install,$dep;$seen{$dep->module}=1}}if (@install){$self->diag("==> Found dependencies: " .join(", ",map $_->module,@install)."\n")}for my$dep (@install){$self->install_module($dep->module,$depth + 1,$dep->version)}$self->chdir($self->{base});$self->chdir($dir)if$dir;if ($self->{scandeps}){return 1}my@not_ok=$self->unsatisfied_deps(@deps);if (@not_ok){return 0,\@not_ok}else {return 1}}sub unsatisfied_deps {my($self,@deps)=@_;require CPAN::Meta::Check;require CPAN::Meta::Requirements;my$reqs=CPAN::Meta::Requirements->new;for my$dep (grep $_->is_requirement,@deps){$reqs->add_string_requirement($dep->module=>$dep->version || '0')}my$ret=CPAN::Meta::Check::check_requirements($reqs,'requires',$self->{search_inc});grep defined,values %$ret}sub install_deps_bailout {my($self,$target,$dir,$depth,@deps)=@_;my($ok,$fail)=$self->install_deps($dir,$depth,@deps);if (!$ok){$self->diag_fail("Installing the dependencies failed: " .join(", ",@$fail),1);unless ($self->prompt_bool("Do you want to continue building $target anyway?","n")){$self->diag_fail("Bailing out the installation for $target.",1);return}}return 1}sub build_stuff {my($self,$stuff,$dist,$depth)=@_;if ($self->{verify}&& -e 'SIGNATURE'){$self->verify_signature($dist)or return}require CPAN::Meta;my($meta_file)=grep -f,qw(META.json META.yml);if ($meta_file){$self->chat("Checking configure dependencies from $meta_file\n");$dist->{cpanmeta}=eval {CPAN::Meta->load_file($meta_file)}}elsif ($dist->{dist}&& $dist->{version}){$self->chat("META.yml/json not found. Creating skeleton for it.\n");$dist->{cpanmeta}=CPAN::Meta->new({name=>$dist->{dist},version=>$dist->{version}})}$dist->{meta}=$dist->{cpanmeta}? $dist->{cpanmeta}->as_struct : {};my@config_deps;if ($dist->{cpanmeta}){push@config_deps,Dependency->from_prereqs($dist->{cpanmeta}->effective_prereqs,['configure'],$self->{install_types},)}else {push@config_deps,Dependency->from_versions($dist->{meta}{configure_requires}|| {},'configure',)}if (-e 'Build.PL' &&!$self->should_use_mm($dist->{dist})){push@config_deps,Dependency->from_versions({'Module::Build'=>'0.36' },'configure',)}my$target=$dist->{meta}{name}? "$dist->{meta}{name}-$dist->{meta}{version}" : $dist->{dir};$self->install_deps_bailout($target,$dist->{dir},$depth,@config_deps)or return;$self->diag_progress("Configuring $target");my$configure_state=$self->configure_this($dist,$depth);$self->diag_ok($configure_state->{configured_ok}? "OK" : "N/A");$dist->{provides}=$self->extract_packages($dist->{cpanmeta},".")if$dist->{cpanmeta}&& $dist->{source}eq 'cpan';my$root_target=(($self->{installdeps}or $self->{showdeps})and $depth==0);$dist->{want_phases}=$self->{notest}&&!$root_target ? [qw(build runtime)]: [qw(build test runtime)];push @{$dist->{want_phases}},'develop' if$self->{with_develop}&& $depth==0;my@deps=$self->find_prereqs($dist);my$module_name=$self->find_module_name($configure_state)|| $dist->{meta}{name};$module_name =~ s/-/::/g;if ($self->{showdeps}){for my$dep (@config_deps,@deps){print$dep->module,($dep->version ? ("~".$dep->version): ""),"\n"}return 1}my$distname=$dist->{meta}{name}? "$dist->{meta}{name}-$dist->{meta}{version}" : $stuff;my$walkup;if ($self->{scandeps}){$walkup=$self->scandeps_append_child($dist)}$self->install_deps_bailout($distname,$dist->{dir},$depth,@deps)or return;if ($self->{scandeps}){unless ($configure_state->{configured_ok}){my$diag=<<DIAG;if (@config_deps){my@tree=@{$self->{scandeps_tree}};$diag .= "!\n" .join("",map "! * $_->[0]{module}\n",@tree[0..$#tree-1])if@tree}$self->diag("!\n$diag!\n",1)}$walkup->();return 1}if ($self->{installdeps}&& $depth==0){if ($configure_state->{configured_ok}){$self->diag("<== Installed dependencies for $stuff. Finishing.\n");return 1}else {$self->diag("! Configuring $distname failed. See $self->{log} for details.\n",1);return}}my$installed;if ($configure_state->{use_module_build}&& -e 'Build' && -f _){$self->diag_progress("Building " .($self->{notest}? "" : "and testing ").$distname);$self->build([$self->{perl},"./Build" ],$distname,$depth)&& $self->test([$self->{perl},"./Build","test" ],$distname,$depth)&& $self->install([$self->{perl},"./Build","install" ],["--uninst",1 ],$depth)&& $installed++}elsif ($self->{make}&& -e 'Makefile'){$self->diag_progress("Building " .($self->{notest}? "" : "and testing ").$distname);$self->build([$self->{make}],$distname,$depth)&& $self->test([$self->{make},"test" ],$distname,$depth)&& $self->install([$self->{make},"install" ],["UNINST=1" ],$depth)&& $installed++}else {my$why;my$configure_failed=$configure_state->{configured}&&!$configure_state->{configured_ok};if ($configure_failed){$why="Configure failed for $distname."}elsif ($self->{make}){$why="The distribution doesn't have a proper Makefile.PL/Build.PL"}else {$why="Can't configure the distribution. You probably need to have 'make'."}$self->diag_fail("$why See $self->{log} for details.",1);return}if ($installed && $self->{test_only}){$self->diag_ok;$self->diag("Successfully tested $distname\n",1)}elsif ($installed){my$local=$self->{local_versions}{$dist->{module}|| ''};my$version=$dist->{module_version}|| $dist->{meta}{version}|| $dist->{version};my$reinstall=$local && ($local eq $version);my$action=$local &&!$reinstall ? $self->numify_ver($version)< $self->numify_ver($local)? "downgraded" : "upgraded" : undef;my$how=$reinstall ? "reinstalled $distname" : $local ? "installed $distname ($action from $local)" : "installed $distname" ;my$msg="Successfully $how";$self->diag_ok;$self->diag("$msg\n",1);$self->{installed_dists}++;$self->save_meta($stuff,$dist,$module_name,\@config_deps,\@deps);return 1}else {my$what=$self->{test_only}? "Testing" : "Installing";$self->diag_fail("$what $stuff failed. See $self->{log} for details. Retry with --force to force install it.",1);return}}sub perl_requirements {my($self,@requires)=@_;my@perl;for my$requires (grep defined,@requires){if (exists$requires->{perl}){push@perl,Dependency->new(perl=>$requires->{perl})}}return@perl}sub should_use_mm {my($self,$dist)=@_;my%should_use_mm=map {$_=>1}qw(version ExtUtils-ParseXS ExtUtils-Install ExtUtils-Manifest);$should_use_mm{$dist}}sub configure_this {my($self,$dist,$depth)=@_;if (-e $self->{cpanfile_path}&& $self->{installdeps}&& $depth==0){require Module::CPANfile;$dist->{cpanfile}=eval {Module::CPANfile->load($self->{cpanfile_path})};$self->diag_fail($@,1)if $@;return {configured=>1,configured_ok=>!!$dist->{cpanfile},use_module_build=>0,}}if ($self->{skip_configure}){my$eumm=-e 'Makefile';my$mb=-e 'Build' && -f _;return {configured=>1,configured_ok=>$eumm || $mb,use_module_build=>$mb,}}my$state={};my$try_eumm=sub {if (-e 'Makefile.PL'){$self->chat("Running Makefile.PL\n");if ($self->configure([$self->{perl},"Makefile.PL" ],$depth)){$state->{configured_ok}=-e 'Makefile'}$state->{configured}++}};my$try_mb=sub {if (-e 'Build.PL'){$self->chat("Running Build.PL\n");if ($self->configure([$self->{perl},"Build.PL" ],$depth)){$state->{configured_ok}=-e 'Build' && -f _}$state->{use_module_build}++;$state->{configured}++}};my@try;if ($dist->{dist}&& $self->should_use_mm($dist->{dist})){@try=($try_eumm,$try_mb)}else {@try=($try_mb,$try_eumm)}for my$try (@try){$try->();last if$state->{configured_ok}}unless ($state->{configured_ok}){while (1){my$ans=lc$self->prompt("Configuring $dist->{dist} failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?","s");last if$ans eq 's';return$self->configure_this($dist,$depth)if$ans eq 'r';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}return$state}sub find_module_name {my($self,$state)=@_;return unless$state->{configured_ok};if ($state->{use_module_build}&& -e "_build/build_params"){my$params=do {open my$in,"_build/build_params";$self->safe_eval(join "",<$in>)};return eval {$params->[2]{module_name}}|| undef}elsif (-e "Makefile"){open my$mf,"Makefile";while (<$mf>){if (/^\#\s+NAME\s+=>\s+(.*)/){return$self->safe_eval($1)}}}return}sub list_files {my$self=shift;if (-e 'MANIFEST'){require ExtUtils::Manifest;my$manifest=eval {ExtUtils::Manifest::manifind()}|| {};return sort {lc$a cmp lc$b}keys %$manifest}else {require File::Find;my@files;my$finder=sub {my$name=$File::Find::name;$name =~ s!\.[/\\]!!;push@files,$name};File::Find::find($finder,".");return sort {lc$a cmp lc$b}@files}}sub extract_packages {my($self,$meta,$dir)=@_;my$try=sub {my$file=shift;return 1 unless$meta->{no_index};return 0 if grep {$file =~ m!^$_/!}@{$meta->{no_index}{directory}|| []};return 0 if grep {$file eq $_}@{$meta->{no_index}{file}|| []};return 1};require App::cpanminus::ParsePM;my@files=grep {/\.pm(?:\.PL)?$/ && $try->($_)}$self->list_files;my$provides={};for my$file (@files){my$parser=App::cpanminus::ParsePM->new($meta);my$packages=$parser->parse($file);while (my($package,$meta)=each %$packages){$provides->{$package}||={file=>$meta->{infile},($meta->{version}eq 'undef')? (): (version=>$meta->{version}),}}}return$provides}sub save_meta {my($self,$module,$dist,$module_name,$config_deps,$build_deps)=@_;return unless$dist->{distvname}&& $dist->{source}eq 'cpan';my$base=($ENV{PERL_MM_OPT}|| '')=~ /INSTALL_BASE=/ ? ($self->install_base($ENV{PERL_MM_OPT})."/lib/perl5"): $Config{sitelibexp};my$provides=$dist->{provides};File::Path::mkpath("blib/meta",0,0777);my$local={name=>$module_name,target=>$module,version=>exists$provides->{$module_name}? ($provides->{$module_name}{version}|| $dist->{version}): $dist->{version},dist=>$dist->{distvname},pathname=>$dist->{pathname},provides=>$provides,};require JSON::PP;open my$fh,">","blib/meta/install.json" or die $!;print$fh JSON::PP::encode_json($local);if (-e "MYMETA.json"){File::Copy::copy("MYMETA.json","blib/meta/MYMETA.json")}my@cmd=(($self->{sudo}? 'sudo' : ()),$^X,'-MExtUtils::Install=install','-e',qq[install({ 'blib/meta' => '$base/$Config{archname}/.meta/$dist->{distvname}' })],);$self->run(\@cmd)}sub _merge_hashref {my($self,@hashrefs)=@_;my%hash;for my$h (@hashrefs){%hash=(%hash,%$h)}return \%hash}sub install_base {my($self,$mm_opt)=@_;$mm_opt =~ /INSTALL_BASE=(\S+)/ and return $1;die "Your PERL_MM_OPT doesn't contain INSTALL_BASE"}sub safe_eval {my($self,$code)=@_;eval$code}sub configure_features {my($self,$dist,@features)=@_;map $_->identifier,grep {$self->effective_feature($dist,$_)}@features}sub effective_feature {my($self,$dist,$feature)=@_;if ($dist->{depth}==0){my$value=$self->{features}{$feature->identifier};return$value if defined$value;return 1 if$self->{features}{__all}}if ($self->{interactive}){require CPAN::Meta::Requirements;$self->diag("[@{[ $feature->description ]}]\n",1);my$req=CPAN::Meta::Requirements->new;for my$phase (@{$dist->{want_phases}}){for my$type (@{$self->{install_types}}){$req->add_requirements($feature->prereqs->requirements_for($phase,$type))}}my$reqs=$req->as_string_hash;my@missing;for my$module (keys %$reqs){if ($self->should_install($module,$req->{$module})){push@missing,$module}}if (@missing){my$howmany=@missing;$self->diag("==> Found missing dependencies: " .join(", ",@missing)."\n",1);local$self->{prompt}=1;return$self->prompt_bool("Install the $howmany optional module(s)?","y")}}return}sub find_prereqs {my($self,$dist)=@_;my@deps=$self->extract_meta_prereqs($dist);if ($dist->{module}=~ /^Bundle::/i){push@deps,$self->bundle_deps($dist)}return@deps}sub extract_meta_prereqs {my($self,$dist)=@_;if ($dist->{cpanfile}){my@features=$self->configure_features($dist,$dist->{cpanfile}->features);my$prereqs=$dist->{cpanfile}->prereqs_with(@features);return Dependency->from_prereqs($prereqs,$dist->{want_phases},$self->{install_types})}my$meta=$dist->{meta};my@deps;if (-e "MYMETA.json"){require JSON::PP;$self->chat("Checking dependencies from MYMETA.json ...\n");my$json=do {open my$in,"<MYMETA.json";local $/;<$in>};my$mymeta=JSON::PP::decode_json($json);if ($mymeta){$meta->{$_}=$mymeta->{$_}for qw(name version);return$self->extract_prereqs($mymeta,$dist)}}if (-e 'MYMETA.yml'){$self->chat("Checking dependencies from MYMETA.yml ...\n");my$mymeta=$self->parse_meta('MYMETA.yml');if ($mymeta){$meta->{$_}=$mymeta->{$_}for qw(name version);return$self->extract_prereqs($mymeta,$dist)}}if (-e '_build/prereqs'){$self->chat("Checking dependencies from _build/prereqs ...\n");my$prereqs=do {open my$in,"_build/prereqs";$self->safe_eval(join "",<$in>)};@deps=$self->extract_prereqs({name=>$meta->{name},version=>$meta->{version},%$prereqs },$dist)}elsif (-e 'Makefile'){$self->chat("Finding PREREQ from Makefile ...\n");open my$mf,"Makefile";while (<$mf>){if (/^\#\s+PREREQ_PM => \{\s*(.*?)\s*\}/){my@all;my@pairs=split ', ',$1;for (@pairs){my ($pkg,$v)=split '=>',$_;push@all,[$pkg,$v ]}my$list=join ", ",map {"'$_->[0]' => $_->[1]"}@all;my$prereq=$self->safe_eval("no strict; +{ $list }");push@deps,Dependency->from_versions($prereq)if$prereq;last}}}return@deps}sub bundle_deps {my($self,$dist)=@_;my@files;File::Find::find({wanted=>sub {push@files,File::Spec->rel2abs($_)if /\.pm/i},no_chdir=>1,},'.');my@deps;for my$file (@files){open my$pod,"<",$file or next;my$in_contents;while (<$pod>){if (/^=head\d\s+CONTENTS/){$in_contents=1}elsif (/^=/){$in_contents=0}elsif ($in_contents){/^(\S+)\s*(\S+)?/ and push@deps,Dependency->new($1,$self->maybe_version($2))}}}return@deps}sub maybe_version {my($self,$string)=@_;return$string && $string =~ /^\.?\d/ ? $string : undef}sub extract_prereqs {my($self,$metadata,$dist)=@_;require CPAN::Meta;my$meta=CPAN::Meta->new($metadata,{lazy_validation=>1 });my@features=$self->configure_features($dist,$meta->features);return Dependency->from_prereqs($meta->effective_prereqs(\@features),$dist->{want_phases},$self->{install_types})}sub cleanup_workdirs {my$self=shift;my$expire=time - 24 * 60 * 60 * $self->{auto_cleanup};my@targets;opendir my$dh,"$self->{home}/work";while (my$e=readdir$dh){next if$e !~ /^(\d+)\.\d+$/;my$time=$1;if ($time < $expire){push@targets,"$self->{home}/work/$e"}}if (@targets){if (@targets >= 64){$self->diag("Expiring " .scalar(@targets)." work directories. This might take long...\n")}else {$self->chat("Expiring " .scalar(@targets)." work directories.\n")}File::Path::rmtree(\@targets,0,0)}}sub scandeps_append_child {my($self,$dist)=@_;my$new_node=[$dist,[]];my$curr_node=$self->{scandeps_current}|| [undef,$self->{scandeps_tree}];push @{$curr_node->[1]},$new_node;$self->{scandeps_current}=$new_node;return sub {$self->{scandeps_current}=$curr_node}}sub dump_scandeps {my$self=shift;if ($self->{format}eq 'tree'){$self->walk_down(sub {my($dist,$depth)=@_;if ($depth==0){print "$dist->{distvname}\n"}else {print " " x ($depth - 1);print "\\_ $dist->{distvname}\n"}},1)}elsif ($self->{format}=~ /^dists?$/){$self->walk_down(sub {my($dist,$depth)=@_;print$self->format_dist($dist),"\n"},0)}elsif ($self->{format}eq 'json'){require JSON::PP;print JSON::PP::encode_json($self->{scandeps_tree})}elsif ($self->{format}eq 'yaml'){require YAML;print YAML::Dump($self->{scandeps_tree})}else {$self->diag("Unknown format: $self->{format}\n")}}sub walk_down {my($self,$cb,$pre)=@_;$self->_do_walk_down($self->{scandeps_tree},$cb,0,$pre)}sub _do_walk_down {my($self,$children,$cb,$depth,$pre)=@_;for my$node (@$children){$cb->($node->[0],$depth)if$pre;$self->_do_walk_down($node->[1],$cb,$depth + 1,$pre);$cb->($node->[0],$depth)unless$pre}}sub DESTROY {my$self=shift;$self->{at_exit}->($self)if$self->{at_exit}}sub shell_quote {my($self,@stuff)=@_;if (WIN32){join ' ',map {/^${quote}.+${quote}$/ ? $_ : ($quote .$_ .$quote)}@stuff}else {String::ShellQuote::shell_quote_best_effort(@stuff)}}sub which {my($self,$name)=@_;return$name if File::Spec->file_name_is_absolute($name)&& -x $name;my$exe_ext=$Config{_exe};for my$dir (File::Spec->path){my$fullpath=File::Spec->catfile($dir,$name);if (-x $fullpath || -x ($fullpath .= $exe_ext)){if ($fullpath =~ /\s/){$fullpath=$self->shell_quote($fullpath)}return$fullpath}}return}sub get {my($self,$uri)=@_;if ($uri =~ /^file:/){$self->file_get($uri)}else {$self->{_backends}{get}->(@_)}}sub mirror {my($self,$uri,$local)=@_;if ($uri =~ /^file:/){$self->file_mirror($uri,$local)}else {$self->{_backends}{mirror}->(@_)}}sub untar {$_[0]->{_backends}{untar}->(@_)};sub unzip {$_[0]->{_backends}{unzip}->(@_)};sub uri_to_file {my($self,$uri)=@_;if ($uri =~ s!file:/+!!){$uri="/$uri" unless$uri =~ m![a-zA-Z]:!}return$uri}sub file_get {my($self,$uri)=@_;my$file=$self->uri_to_file($uri);open my$fh,"<$file" or return;join '',<$fh>}sub file_mirror {my($self,$uri,$path)=@_;my$file=$self->uri_to_file($uri);File::Copy::copy($file,$path)}sub has_working_lwp {my($self,$mirrors)=@_;my$https=grep /^https:/,@$mirrors;eval {require LWP::UserAgent;LWP::UserAgent->VERSION(5.802);require LWP::Protocol::https if$https;1}}sub init_tools {my$self=shift;return if$self->{initialized}++;if ($self->{make}=$self->which($Config{make})){$self->chat("You have make $self->{make}\n")}if ($self->{try_lwp}&& $self->has_working_lwp($self->{mirrors})){$self->chat("You have LWP $LWP::VERSION\n");my$ua=sub {LWP::UserAgent->new(parse_head=>0,env_proxy=>1,agent=>$self->agent,timeout=>30,@_,)};$self->{_backends}{get}=sub {my$self=shift;my$res=$ua->()->request(HTTP::Request->new(GET=>$_[0]));return unless$res->is_success;return$res->decoded_content};$self->{_backends}{mirror}=sub {my$self=shift;my$res=$ua->()->mirror(@_);die$res->content if$res->code==501;$res->code}}elsif ($self->{try_wget}and my$wget=$self->which('wget')){$self->chat("You have $wget\n");my@common=('--user-agent',$self->agent,'--retry-connrefused',($self->{verbose}? (): ('-q')),);$self->{_backends}{get}=sub {my($self,$uri)=@_;$self->safeexec(my$fh,$wget,$uri,@common,'-O','-')or die "wget $uri: $!";local $/;<$fh>};$self->{_backends}{mirror}=sub {my($self,$uri,$path)=@_;$self->safeexec(my$fh,$wget,$uri,@common,'-O',$path)or die "wget $uri: $!";local $/;<$fh>}}elsif ($self->{try_curl}and my$curl=$self->which('curl')){$self->chat("You have $curl\n");my@common=('--location','--user-agent',$self->agent,($self->{verbose}? (): '-s'),);$self->{_backends}{get}=sub {my($self,$uri)=@_;$self->safeexec(my$fh,$curl,@common,$uri)or die "curl $uri: $!";local $/;<$fh>};$self->{_backends}{mirror}=sub {my($self,$uri,$path)=@_;$self->safeexec(my$fh,$curl,@common,$uri,'-#','-o',$path)or die "curl $uri: $!";local $/;<$fh>}}else {require HTTP::Tiny;$self->chat("Falling back to HTTP::Tiny $HTTP::Tiny::VERSION\n");my%common=(agent=>$self->agent,);$self->{_backends}{get}=sub {my$self=shift;my$res=HTTP::Tiny->new(%common)->get($_[0]);return unless$res->{success};return$res->{content}};$self->{_backends}{mirror}=sub {my$self=shift;my$res=HTTP::Tiny->new(%common)->mirror(@_);return$res->{status}}}my$tar=$self->which('tar');my$tar_ver;my$maybe_bad_tar=sub {WIN32 || SUNOS || (($tar_ver=`$tar --version 2>/dev/null`)=~ /GNU.*1\.13/i)};if ($tar &&!$maybe_bad_tar->()){chomp$tar_ver;$self->chat("You have $tar: $tar_ver\n");$self->{_backends}{untar}=sub {my($self,$tarfile)=@_;my$xf=($self->{verbose}? 'v' : '')."xf";my$ar=$tarfile =~ /bz2$/ ? 'j' : 'z';my($root,@others)=`$tar ${ar}tf $tarfile` or return undef;FILE: {chomp$root;$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}system "$tar $ar$xf $tarfile";return$root if -d $root;$self->diag_fail("Bad archive: $tarfile");return undef}}elsif ($tar and my$gzip=$self->which('gzip')and my$bzip2=$self->which('bzip2')){$self->chat("You have $tar, $gzip and $bzip2\n");$self->{_backends}{untar}=sub {my($self,$tarfile)=@_;my$x="x" .($self->{verbose}? 'v' : '')."f -";my$ar=$tarfile =~ /bz2$/ ? $bzip2 : $gzip;my($root,@others)=`$ar -dc $tarfile | $tar tf -` or return undef;FILE: {chomp$root;$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}system "$ar -dc $tarfile | $tar $x";return$root if -d $root;$self->diag_fail("Bad archive: $tarfile");return undef}}elsif (eval {require Archive::Tar}){$self->chat("Falling back to Archive::Tar $Archive::Tar::VERSION\n");$self->{_backends}{untar}=sub {my$self=shift;my$t=Archive::Tar->new($_[0]);my($root,@others)=$t->list_files;FILE: {$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}$t->extract;return -d $root ? $root : undef}}else {$self->{_backends}{untar}=sub {die "Failed to extract $_[1] - You need to have tar or Archive::Tar installed.\n"}}if (my$unzip=$self->which('unzip')){$self->chat("You have $unzip\n");$self->{_backends}{unzip}=sub {my($self,$zipfile)=@_;my$opt=$self->{verbose}? '' : '-q';my(undef,$root,@others)=`$unzip -t $zipfile` or return undef;chomp$root;$root =~ s{^\s+testing:\s+([^/]+)/.*?\s+OK$}{$1};system "$unzip $opt $zipfile";return$root if -d $root;$self->diag_fail("Bad archive: [$root] $zipfile");return undef}}else {$self->{_backends}{unzip}=sub {eval {require Archive::Zip}or die "Failed to extract $_[1] - You need to have unzip or Archive::Zip installed.\n";my($self,$file)=@_;my$zip=Archive::Zip->new();my$status;$status=$zip->read($file);$self->diag_fail("Read of file[$file] failed")if$status!=Archive::Zip::AZ_OK();my@members=$zip->members();for my$member (@members){my$af=$member->fileName();next if ($af =~ m!^(/|\.\./)!);$status=$member->extractToFileNamed($af);$self->diag_fail("Extracting of file[$af] from zipfile[$file failed")if$status!=Archive::Zip::AZ_OK()}my ($root)=$zip->membersMatching(qr<^[^/]+/$>);$root &&=$root->fileName;return -d $root ? $root : undef}}}sub safeexec {my$self=shift;my$rdr=$_[0]||=Symbol::gensym();if (WIN32){my$cmd=$self->shell_quote(@_[1..$#_]);return open($rdr,"$cmd |")}if (my$pid=open($rdr,'-|')){return$pid}elsif (defined$pid){exec(@_[1 .. $#_ ]);exit 1}else {return}}sub mask_uri_passwords {my($self,@strings)=@_;s{ (https?://) ([^:/]+) : [^@/]+ @ }{$1$2:*password*@}gx for@strings;return@strings}sub parse_meta {my($self,$file)=@_;return eval {Parse::CPAN::Meta->load_file($file)}}sub parse_meta_string {my($self,$yaml)=@_;return eval {Parse::CPAN::Meta->load_yaml_string($yaml)}}package App::cpanminus::CommandExit;sub new {bless {code=>$_[1]},$_[0]}sub code {$_[0]->{code}}1;
+$fatpacked{"App/cpanminus/script.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_SCRIPT';
+  package App::cpanminus::script;use strict;use Config;use Cwd ();use App::cpanminus;use File::Basename ();use File::Find ();use File::Path ();use File::Spec ();use File::Copy ();use File::Temp ();use Getopt::Long ();use Parse::CPAN::Meta;use Symbol ();use String::ShellQuote ();use version ();use aliased 'App::cpanminus::Dependency';use constant WIN32=>$^O eq 'MSWin32';use constant SUNOS=>$^O eq 'solaris';use constant CAN_SYMLINK=>eval {symlink("","");1};our$VERSION=$App::cpanminus::VERSION;if ($INC{"App/FatPacker/Trace.pm"}){require JSON::PP;require CPAN::Meta::YAML;require CPAN::Meta::Prereqs;require version::vpp;require File::pushd}my$quote=WIN32 ? q/"/ : q/'/;sub agent {my$self=shift;my$agent="cpanminus/$VERSION";$agent .= " perl/$]" if$self->{report_perl_version};$agent}sub determine_home {my$class=shift;my$homedir=$ENV{HOME}|| eval {require File::HomeDir;File::HomeDir->my_home}|| join('',@ENV{qw(HOMEDRIVE HOMEPATH)});if (WIN32){require Win32;$homedir=Win32::GetShortPathName($homedir)}return "$homedir/.cpanm"}sub new {my$class=shift;bless {home=>$class->determine_home,cmd=>'install',seen=>{},notest=>undef,test_only=>undef,installdeps=>undef,force=>undef,sudo=>undef,make=>undef,verbose=>undef,quiet=>undef,interactive=>undef,log=>undef,mirrors=>[],mirror_only=>undef,mirror_index=>undef,cpanmetadb=>"http://cpanmetadb.plackperl.org/v1.0/",perl=>$^X,argv=>[],local_lib=>undef,self_contained=>undef,prompt_timeout=>0,prompt=>undef,configure_timeout=>60,build_timeout=>3600,test_timeout=>1800,try_lwp=>1,try_wget=>1,try_curl=>1,uninstall_shadows=>($] < 5.012),skip_installed=>1,skip_satisfied=>0,auto_cleanup=>7,pod2man=>1,installed_dists=>0,install_types=>['requires'],with_develop=>0,showdeps=>0,scandeps=>0,scandeps_tree=>[],format=>'tree',save_dists=>undef,skip_configure=>0,verify=>0,report_perl_version=>1,build_args=>{},features=>{},pure_perl=>0,cpanfile_path=>'cpanfile',@_,},$class}sub env {my($self,$key)=@_;$ENV{"PERL_CPANM_" .$key}}sub install_type_handlers {my$self=shift;my@handlers;for my$type (qw(recommends suggests)){push@handlers,"with-$type"=>sub {my%uniq;$self->{install_types}=[grep!$uniq{$_}++,@{$self->{install_types}},$type ]};push@handlers,"without-$type"=>sub {$self->{install_types}=[grep $_ ne $type,@{$self->{install_types}}]}}@handlers}sub build_args_handlers {my$self=shift;my@handlers;for my$phase (qw(configure build test install)){push@handlers,"$phase-args=s"=>\($self->{build_args}{$phase})}@handlers}sub parse_options {my$self=shift;local@ARGV=@{$self->{argv}};push@ARGV,grep length,split /\s+/,$self->env('OPT');push@ARGV,@_;Getopt::Long::Configure("bundling");Getopt::Long::GetOptions('f|force'=>sub {$self->{skip_installed}=0;$self->{force}=1},'n|notest!'=>\$self->{notest},'test-only'=>sub {$self->{notest}=0;$self->{skip_installed}=0;$self->{test_only}=1},'S|sudo!'=>\$self->{sudo},'v|verbose'=>\$self->{verbose},'verify!'=>\$self->{verify},'q|quiet!'=>\$self->{quiet},'h|help'=>sub {$self->{action}='show_help'},'V|version'=>sub {$self->{action}='show_version'},'perl=s'=>\$self->{perl},'l|local-lib=s'=>sub {$self->{local_lib}=$self->maybe_abs($_[1])},'L|local-lib-contained=s'=>sub {$self->{local_lib}=$self->maybe_abs($_[1]);$self->{self_contained}=1;$self->{pod2man}=undef},'self-contained!'=>\$self->{self_contained},'mirror=s@'=>$self->{mirrors},'mirror-only!'=>\$self->{mirror_only},'mirror-index=s'=>\$self->{mirror_index},'cpanmetadb=s'=>\$self->{cpanmetadb},'cascade-search!'=>\$self->{cascade_search},'prompt!'=>\$self->{prompt},'installdeps'=>\$self->{installdeps},'skip-installed!'=>\$self->{skip_installed},'skip-satisfied!'=>\$self->{skip_satisfied},'reinstall'=>sub {$self->{skip_installed}=0},'interactive!'=>\$self->{interactive},'i|install'=>sub {$self->{cmd}='install'},'info'=>sub {$self->{cmd}='info'},'look'=>sub {$self->{cmd}='look';$self->{skip_installed}=0},'U|uninstall'=>sub {$self->{cmd}='uninstall'},'self-upgrade'=>sub {$self->{action}='self_upgrade'},'uninst-shadows!'=>\$self->{uninstall_shadows},'lwp!'=>\$self->{try_lwp},'wget!'=>\$self->{try_wget},'curl!'=>\$self->{try_curl},'auto-cleanup=s'=>\$self->{auto_cleanup},'man-pages!'=>\$self->{pod2man},'scandeps'=>\$self->{scandeps},'showdeps'=>sub {$self->{showdeps}=1;$self->{skip_installed}=0},'format=s'=>\$self->{format},'save-dists=s'=>sub {$self->{save_dists}=$self->maybe_abs($_[1])},'skip-configure!'=>\$self->{skip_configure},'dev!'=>\$self->{dev_release},'metacpan!'=>\$self->{metacpan},'report-perl-version!'=>\$self->{report_perl_version},'configure-timeout=i'=>\$self->{configure_timeout},'build-timeout=i'=>\$self->{build_timeout},'test-timeout=i'=>\$self->{test_timeout},'with-develop'=>\$self->{with_develop},'without-develop'=>sub {$self->{with_develop}=0},'with-feature=s'=>sub {$self->{features}{$_[1]}=1},'without-feature=s'=>sub {$self->{features}{$_[1]}=0},'with-all-features'=>sub {$self->{features}{__all}=1},'pp|pureperl!'=>\$self->{pure_perl},"cpanfile=s"=>\$self->{cpanfile_path},$self->install_type_handlers,$self->build_args_handlers,);if (!@ARGV && $0 ne '-' &&!-t STDIN){push@ARGV,$self->load_argv_from_fh(\*STDIN);$self->{load_from_stdin}=1}$self->{argv}=\@ARGV}sub check_upgrade {my$self=shift;my$install_base=$ENV{PERL_LOCAL_LIB_ROOT}? $self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}): $Config{installsitebin};if ($0 eq '-'){return}elsif ($0 !~ /^$install_base/){if ($0 =~ m!perlbrew/bin!){die <<DIE}else {die <<DIE}}}sub check_libs {my$self=shift;return if$self->{_checked}++;$self->bootstrap_local_lib;if (@{$self->{bootstrap_deps}|| []}){local$self->{notest}=1;local$self->{scandeps}=0;$self->install_deps(Cwd::cwd,0,@{$self->{bootstrap_deps}})}}sub setup_verify {my$self=shift;my$has_modules=eval {require Module::Signature;require Digest::SHA;1};$self->{cpansign}=$self->which('cpansign');unless ($has_modules && $self->{cpansign}){warn "WARNING: Module::Signature and Digest::SHA is required for distribution verifications.\n";$self->{verify}=0}}sub parse_module_args {my($self,$module)=@_;$module =~ s/^([A-Za-z0-9_:]+)@([v\d\._]+)$/$1~== $2/;if ($module =~ /\~[v\d\._,\!<>= ]+$/){return split /\~/,$module,2}else {return$module,undef}}sub _exit {my($self,$code)=@_;die App::cpanminus::CommandExit->new($code)}sub doit {my$self=shift;my$code;eval {$code=($self->_doit==0)};if (my$e=$@){if (ref$e eq 'App::cpanminus::CommandExit'){$code=$e->code}else {warn$e;$code=1}}return$code}sub _doit {my$self=shift;$self->setup_home;$self->init_tools;$self->setup_verify if$self->{verify};if (my$action=$self->{action}){$self->$action()and return 1}$self->show_help(1)unless @{$self->{argv}}or $self->{load_from_stdin};$self->configure_mirrors;my$cwd=Cwd::cwd;my@fail;for my$module (@{$self->{argv}}){if ($module =~ s/\.pm$//i){my ($volume,$dirs,$file)=File::Spec->splitpath($module);$module=join '::',grep {$_}File::Spec->splitdir($dirs),$file}($module,my$version)=$self->parse_module_args($module);$self->chdir($cwd);if ($self->{cmd}eq 'uninstall'){$self->uninstall_module($module)or push@fail,$module}else {$self->install_module($module,0,$version)or push@fail,$module}}if ($self->{base}&& $self->{auto_cleanup}){$self->cleanup_workdirs}if ($self->{installed_dists}){my$dists=$self->{installed_dists}> 1 ? "distributions" : "distribution";$self->diag("$self->{installed_dists} $dists installed\n",1)}if ($self->{scandeps}){$self->dump_scandeps()}$self->chdir($cwd);return!@fail}sub setup_home {my$self=shift;$self->{home}=$self->env('HOME')if$self->env('HOME');unless (_writable($self->{home})){die "Can't write to cpanm home '$self->{home}': You should fix it with chown/chmod first.\n"}$self->{base}="$self->{home}/work/" .time .".$$";File::Path::mkpath([$self->{base}],0,0777);$self->{log}=File::Spec->catfile($self->{base},"build.log");my$final_log="$self->{home}/build.log";{open my$out,">$self->{log}" or die "$self->{log}: $!"}if (CAN_SYMLINK){my$build_link="$self->{home}/latest-build";unlink$build_link;symlink$self->{base},$build_link;unlink$final_log;symlink$self->{log},$final_log}else {my$log=$self->{log};my$home=$self->{home};$self->{at_exit}=sub {my$self=shift;my$temp_log="$home/build.log." .time .".$$";File::Copy::copy($log,$temp_log)&& unlink($final_log);rename($temp_log,$final_log)}}$self->chat("cpanm (App::cpanminus) $VERSION on perl $] built for $Config{archname}\n" ."Work directory is $self->{base}\n")}sub package_index_for {my ($self,$mirror)=@_;return$self->source_for($mirror)."/02packages.details.txt"}sub generate_mirror_index {my ($self,$mirror)=@_;my$file=$self->package_index_for($mirror);my$gz_file=$file .'.gz';my$index_mtime=(stat$gz_file)[9];unless (-e $file && (stat$file)[9]>= $index_mtime){$self->chat("Uncompressing index file...\n");if (eval {require Compress::Zlib}){my$gz=Compress::Zlib::gzopen($gz_file,"rb")or do {$self->diag_fail("$Compress::Zlib::gzerrno opening compressed index");return};open my$fh,'>',$file or do {$self->diag_fail("$! opening uncompressed index for write");return};my$buffer;while (my$status=$gz->gzread($buffer)){if ($status < 0){$self->diag_fail($gz->gzerror ." reading compressed index");return}print$fh $buffer}}else {if (system("gunzip -c $gz_file > $file")){$self->diag_fail("Cannot uncompress -- please install gunzip or Compress::Zlib");return}}utime$index_mtime,$index_mtime,$file}return 1}sub search_mirror_index {my ($self,$mirror,$module,$version)=@_;$self->search_mirror_index_file($self->package_index_for($mirror),$module,$version)}sub search_mirror_index_file {my($self,$file,$module,$version)=@_;open my$fh,'<',$file or return;my$found;while (<$fh>){if (m!^\Q$module\E\s+([\w\.]+)\s+(\S*)!m){$found=$self->cpan_module($module,$2,$1);last}}return$found unless$self->{cascade_search};if ($found){if ($self->satisfy_version($module,$found->{module_version},$version)){return$found}else {$self->chat("Found $module $found->{module_version} which doesn't satisfy $version.\n")}}return}sub with_version_range {my($self,$version)=@_;defined($version)&& $version =~ /[<>=]/}sub encode_json {my($self,$data)=@_;require JSON::PP;my$json=JSON::PP::encode_json($data);$json =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;$json}sub version_to_query {my($self,$module,$version)=@_;require CPAN::Meta::Requirements;my$requirements=CPAN::Meta::Requirements->new;$requirements->add_string_requirement($module,$version || '0');my$req=$requirements->requirements_for_module($module);if ($req =~ s/^==\s*//){return {term=>{'module.version'=>$req },}}elsif ($req !~ /\s/){return {range=>{'module.version_numified'=>{'gte'=>$self->numify_ver($req)}},}}else {my%ops=qw(< lt <= lte > gt >= gte);my(%range,@exclusion);my@requirements=split /,\s*/,$req;for my$r (@requirements){if ($r =~ s/^([<>]=?)\s*//){$range{$ops{$1}}=$self->numify_ver($r)}elsif ($r =~ s/\!=\s*//){push@exclusion,$self->numify_ver($r)}}my@filters=({range=>{'module.version_numified'=>\%range }},);if (@exclusion){push@filters,{not=>{or=>[map {+{term=>{'module.version_numified'=>$self->numify_ver($_)}}}@exclusion ]},}}return@filters}}sub numify_ver {my($self,$ver)=@_;version->new($ver)->numify}sub maturity_filter {my($self,$module,$version)=@_;my@filters;if (!$self->with_version_range($version)or $self->{dev_release}){push@filters,{not=>{term=>{status=>'backpan' }}}}unless ($self->{dev_release}or $version =~ /==/){push@filters,{term=>{maturity=>'released' }}}return@filters}sub by_version {my%s=qw(latest 3 cpan 2 backpan 1);$b->{_score}<=> $a->{_score}|| $s{$b->{fields}{status}}<=> $s{$a->{fields}{status}}}sub by_first_come {$a->{fields}{date}cmp $b->{fields}{date}}sub by_date {$b->{fields}{date}cmp $a->{fields}{date}}sub find_best_match {my($self,$match,$version)=@_;return unless$match && @{$match->{hits}{hits}|| []};my@hits=$self->{dev_release}? sort {by_version || by_date}@{$match->{hits}{hits}}: sort {by_version || by_first_come}@{$match->{hits}{hits}};$hits[0]->{fields}}sub search_metacpan {my($self,$module,$version)=@_;require JSON::PP;$self->chat("Searching $module ($version) on metacpan ...\n");my$metacpan_uri='http://api.metacpan.org/v0';my@filter=$self->maturity_filter($module,$version);my$query={filtered=>{(@filter ? (filter=>{and=>\@filter }): ()),query=>{nested=>{score_mode=>'max',path=>'module',query=>{custom_score=>{metacpan_script=>"score_version_numified",query=>{constant_score=>{filter=>{and=>[{term=>{'module.authorized'=>JSON::PP::true()}},{term=>{'module.indexed'=>JSON::PP::true()}},{term=>{'module.name'=>$module }},$self->version_to_query($module,$version),]}}},}},}},}};my$module_uri="$metacpan_uri/file/_search?source=";$module_uri .= $self->encode_json({query=>$query,fields=>['date','release','module','status' ],});my($release,$module_version);my$module_json=$self->get($module_uri);my$module_meta=eval {JSON::PP::decode_json($module_json)};my$match=$self->find_best_match($module_meta);if ($match){$release=$match->{release};my$module_matched=(grep {$_->{name}eq $module}@{$match->{module}})[0];$module_version=$module_matched->{version}}unless ($release){$self->chat("! Could not find a release matching $module ($version) on MetaCPAN.\n");return}my$dist_uri="$metacpan_uri/release/_search?source=";$dist_uri .= $self->encode_json({filter=>{term=>{'release.name'=>$release },},fields=>['download_url','stat','status' ],});my$dist_json=$self->get($dist_uri);my$dist_meta=eval {JSON::PP::decode_json($dist_json)};if ($dist_meta){$dist_meta=$dist_meta->{hits}{hits}[0]{fields}}if ($dist_meta && $dist_meta->{download_url}){(my$distfile=$dist_meta->{download_url})=~ s!.+/authors/id/!!;local$self->{mirrors}=$self->{mirrors};if ($dist_meta->{status}eq 'backpan'){$self->{mirrors}=['http://backpan.perl.org' ]}elsif ($dist_meta->{stat}{mtime}> time()-24*60*60){$self->{mirrors}=['http://cpan.metacpan.org' ]}return$self->cpan_module($module,$distfile,$module_version)}$self->diag_fail("Finding $module on metacpan failed.");return}sub search_database {my($self,$module,$version)=@_;my$found;my$range=($self->with_version_range($version)|| $self->{dev_release});if ($range or $self->{metacpan}){$found=$self->search_metacpan($module,$version)and return$found;$found=$self->search_cpanmetadb($module,$version)and return$found}else {$found=$self->search_cpanmetadb($module,$version)and return$found;$found=$self->search_metacpan($module,$version)and return$found}}sub search_cpanmetadb {my($self,$module,$version)=@_;$self->chat("Searching $module on cpanmetadb ...\n");(my$uri=$self->{cpanmetadb})=~ s{/?$}{/package/$module};my$yaml=$self->get($uri);my$meta=$self->parse_meta_string($yaml);if ($meta && $meta->{distfile}){return$self->cpan_module($module,$meta->{distfile},$meta->{version})}$self->diag_fail("Finding $module on cpanmetadb failed.");return}sub search_module {my($self,$module,$version)=@_;if ($self->{mirror_index}){$self->mask_output(chat=>"Searching $module on mirror index $self->{mirror_index} ...\n");my$pkg=$self->search_mirror_index_file($self->{mirror_index},$module,$version);return$pkg if$pkg;unless ($self->{cascade_search}){$self->mask_output(diag_fail=>"Finding $module ($version) on mirror index $self->{mirror_index} failed.");return}}unless ($self->{mirror_only}){my$found=$self->search_database($module,$version);return$found if$found}MIRROR: for my$mirror (@{$self->{mirrors}}){$self->mask_output(chat=>"Searching $module on mirror $mirror ...\n");my$name='02packages.details.txt.gz';my$uri="$mirror/modules/$name";my$gz_file=$self->package_index_for($mirror).'.gz';unless ($self->{pkgs}{$uri}){$self->mask_output(chat=>"Downloading index file $uri ...\n");$self->mirror($uri,$gz_file);$self->generate_mirror_index($mirror)or next MIRROR;$self->{pkgs}{$uri}="!!retrieved!!"}my$pkg=$self->search_mirror_index($mirror,$module,$version);return$pkg if$pkg;$self->mask_output(diag_fail=>"Finding $module ($version) on mirror $mirror failed.")}return}sub source_for {my($self,$mirror)=@_;$mirror =~ s/[^\w\.\-]+/%/g;my$dir="$self->{home}/sources/$mirror";File::Path::mkpath([$dir ],0,0777);return$dir}sub load_argv_from_fh {my($self,$fh)=@_;my@argv;while(defined(my$line=<$fh>)){chomp$line;$line =~ s/#.+$//;$line =~ s/^\s+//;$line =~ s/\s+$//;push@argv,split ' ',$line if$line}return@argv}sub show_version {my$self=shift;print "cpanm (App::cpanminus) version $VERSION ($0)\n";print "perl version $] ($^X)\n\n";print "  \%Config:\n";for my$key (qw(archname installsitelib installsitebin installman1dir installman3dir sitelibexp archlibexp privlibexp)){print "    $key=$Config{$key}\n"}print "  \%ENV:\n";for my$key (grep /^PERL/,sort keys%ENV){print "    $key=$ENV{$key}\n"}print "  \@INC:\n";for my$inc (@INC){print "    $inc\n" unless ref($inc)eq 'CODE'}return 1}sub show_help {my$self=shift;if ($_[0]){print <<USAGE;$self->_exit(1)}print <<HELP;return 1}sub _writable {my$dir=shift;my@dir=File::Spec->splitdir($dir);while (@dir){$dir=File::Spec->catdir(@dir);if (-e $dir){return -w _}pop@dir}return}sub maybe_abs {my($self,$lib)=@_;if ($lib eq '_' or $lib =~ /^~/ or File::Spec->file_name_is_absolute($lib)){return$lib}else {return File::Spec->canonpath(File::Spec->catdir(Cwd::cwd(),$lib))}}sub local_lib_target {my($self,$root)=@_;(grep {$_ ne ''}split /\Q$Config{path_sep}/,$root)[0]}sub bootstrap_local_lib {my$self=shift;if ($self->{local_lib}){return$self->setup_local_lib($self->{local_lib})}if ($ENV{PERL_LOCAL_LIB_ROOT}&& $ENV{PERL_MM_OPT}){return$self->setup_local_lib($self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}),1)}return if$self->{sudo}or (_writable($Config{installsitelib})and _writable($Config{installsitebin}));if ($ENV{PERL_MM_OPT}and ($ENV{MODULEBUILDRC}or $ENV{PERL_MB_OPT})){$self->bootstrap_local_lib_deps;return}$self->setup_local_lib;$self->diag(<<DIAG,1);sleep 2}sub _core_only_inc {my($self,$base)=@_;require local::lib;(local::lib->resolve_path(local::lib->install_base_perl_path($base)),local::lib->resolve_path(local::lib->install_base_arch_path($base)),@Config{qw(privlibexp archlibexp)},)}sub _diff {my($self,$old,$new)=@_;my@diff;my%old=map {$_=>1}@$old;for my$n (@$new){push@diff,$n unless exists$old{$n}}@diff}sub _setup_local_lib_env {my($self,$base)=@_;$self->diag(<<WARN,1)if$base =~ /\s/;local$SIG{__WARN__}=sub {};local::lib->setup_env_hash_for($base,0)}sub setup_local_lib {my($self,$base,$no_env)=@_;$base=undef if$base eq '_';require local::lib;{local $0='cpanm';$base ||="~/perl5";$base=local::lib->resolve_path($base);if ($self->{self_contained}){my@inc=$self->_core_only_inc($base);$self->{search_inc}=[@inc ]}else {$self->{search_inc}=[local::lib->install_base_arch_path($base),local::lib->install_base_perl_path($base),@INC,]}$self->_setup_local_lib_env($base)unless$no_env;$self->{local_lib}=$base}$self->bootstrap_local_lib_deps}sub bootstrap_local_lib_deps {my$self=shift;push @{$self->{bootstrap_deps}},Dependency->new('ExtUtils::MakeMaker'=>6.31),Dependency->new('ExtUtils::Install'=>1.46)}sub prompt_bool {my($self,$mess,$def)=@_;my$val=$self->prompt($mess,$def);return lc$val eq 'y'}sub prompt {my($self,$mess,$def)=@_;my$isa_tty=-t STDIN && (-t STDOUT ||!(-f STDOUT || -c STDOUT));my$dispdef=defined$def ? "[$def] " : " ";$def=defined$def ? $def : "";if (!$self->{prompt}|| (!$isa_tty && eof STDIN)){return$def}local $|=1;local $\;my$ans;eval {local$SIG{ALRM}=sub {undef$ans;die "alarm\n"};print STDOUT "$mess $dispdef";alarm$self->{prompt_timeout}if$self->{prompt_timeout};$ans=<STDIN>;alarm 0};if (defined$ans){chomp$ans}else {print STDOUT "\n"}return (!defined$ans || $ans eq '')? $def : $ans}sub diag_ok {my($self,$msg)=@_;chomp$msg;$msg ||="OK";if ($self->{in_progress}){$self->_diag("$msg\n");$self->{in_progress}=0}$self->log("-> $msg\n")}sub diag_fail {my($self,$msg,$always)=@_;chomp$msg;if ($self->{in_progress}){$self->_diag("FAIL\n");$self->{in_progress}=0}if ($msg){$self->_diag("! $msg\n",$always,1);$self->log("-> FAIL $msg\n")}}sub diag_progress {my($self,$msg)=@_;chomp$msg;$self->{in_progress}=1;$self->_diag("$msg ... ");$self->log("$msg\n")}sub _diag {my($self,$msg,$always,$error)=@_;my$fh=$error ? *STDERR : *STDOUT;print {$fh}$msg if$always or $self->{verbose}or!$self->{quiet}}sub diag {my($self,$msg,$always)=@_;$self->_diag($msg,$always);$self->log($msg)}sub chat {my$self=shift;print STDERR @_ if$self->{verbose};$self->log(@_)}sub mask_output {my$self=shift;my$method=shift;$self->$method($self->mask_uri_passwords(@_))}sub log {my$self=shift;open my$out,">>$self->{log}";print$out @_}sub run {my($self,$cmd)=@_;if (WIN32){$cmd=$self->shell_quote(@$cmd)if ref$cmd eq 'ARRAY';unless ($self->{verbose}){$cmd .= " >> " .$self->shell_quote($self->{log})." 2>&1"}!system$cmd}else {my$pid=fork;if ($pid){waitpid$pid,0;return!$?}else {$self->run_exec($cmd)}}}sub run_exec {my($self,$cmd)=@_;if (ref$cmd eq 'ARRAY'){unless ($self->{verbose}){open my$logfh,">>",$self->{log};open STDERR,'>&',$logfh;open STDOUT,'>&',$logfh;close$logfh}exec @$cmd}else {unless ($self->{verbose}){$cmd .= " >> " .$self->shell_quote($self->{log})." 2>&1"}exec$cmd}}sub run_timeout {my($self,$cmd,$timeout)=@_;return$self->run($cmd)if WIN32 || $self->{verbose}||!$timeout;my$pid=fork;if ($pid){eval {local$SIG{ALRM}=sub {die "alarm\n"};alarm$timeout;waitpid$pid,0;alarm 0};if ($@ && $@ eq "alarm\n"){$self->diag_fail("Timed out (> ${timeout}s). Use --verbose to retry.");local$SIG{TERM}='IGNORE';kill TERM=>0;waitpid$pid,0;return}return!$?}elsif ($pid==0){$self->run_exec($cmd)}else {$self->chat("! fork failed: falling back to system()\n");$self->run($cmd)}}sub append_args {my($self,$cmd,$phase)=@_;if (my$args=$self->{build_args}{$phase}){$cmd=join ' ',$self->shell_quote(@$cmd),$args}$cmd}sub configure {my($self,$cmd,$depth)=@_;local$ENV{PERL5_CPAN_IS_RUNNING}=local$ENV{PERL5_CPANPLUS_IS_RUNNING}=$$;local$ENV{PERL5_CPANM_IS_RUNNING}=$$;my$use_default=!$self->{interactive};local$ENV{PERL_MM_USE_DEFAULT}=$use_default;local$ENV{PERL_MM_OPT}=$ENV{PERL_MM_OPT};local$ENV{PERL_MB_OPT}=$ENV{PERL_MB_OPT};unless ($self->{pod2man}){$ENV{PERL_MM_OPT}.= " INSTALLMAN1DIR=none INSTALLMAN3DIR=none";$ENV{PERL_MB_OPT}.= " --config installman1dir= --config installsiteman1dir= --config installman3dir= --config installsiteman3dir="}if ($self->{pure_perl}){$ENV{PERL_MM_OPT}.= " PUREPERL_ONLY=1";$ENV{PERL_MB_OPT}.= " --pureperl-only"}$cmd=$self->append_args($cmd,'configure')if$depth==0;local$self->{verbose}=$self->{verbose}|| $self->{interactive};$self->run_timeout($cmd,$self->{configure_timeout})}sub build {my($self,$cmd,$distname,$depth)=@_;local$ENV{PERL_MM_USE_DEFAULT}=!$self->{interactive};$cmd=$self->append_args($cmd,'build')if$depth==0;return 1 if$self->run_timeout($cmd,$self->{build_timeout});while (1){my$ans=lc$self->prompt("Building $distname failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?","s");return if$ans eq 's';return$self->build($cmd,$distname,$depth)if$ans eq 'r';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}sub test {my($self,$cmd,$distname,$depth)=@_;return 1 if$self->{notest};local$ENV{PERL_MM_USE_DEFAULT}=!$self->{interactive};local$ENV{NONINTERACTIVE_TESTING}=!$self->{interactive};$cmd=$self->append_args($cmd,'test')if$depth==0;return 1 if$self->run_timeout($cmd,$self->{test_timeout});if ($self->{force}){$self->diag_fail("Testing $distname failed but installing it anyway.");return 1}else {$self->diag_fail;while (1){my$ans=lc$self->prompt("Testing $distname failed.\nYou can s)kip, r)etry, f)orce install, e)xamine build log, or l)ook ?","s");return if$ans eq 's';return$self->test($cmd,$distname,$depth)if$ans eq 'r';return 1 if$ans eq 'f';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}}sub install {my($self,$cmd,$uninst_opts,$depth)=@_;if ($depth==0 && $self->{test_only}){return 1}if ($self->{sudo}){unshift @$cmd,"sudo"}if ($self->{uninstall_shadows}&&!$ENV{PERL_MM_OPT}){push @$cmd,@$uninst_opts}$cmd=$self->append_args($cmd,'install')if$depth==0;$self->run($cmd)}sub look {my$self=shift;my$shell=$ENV{SHELL};$shell ||=$ENV{COMSPEC}if WIN32;if ($shell){my$cwd=Cwd::cwd;$self->diag("Entering $cwd with $shell\n");system$shell}else {$self->diag_fail("You don't seem to have a SHELL :/")}}sub show_build_log {my$self=shift;my@pagers=($ENV{PAGER},(WIN32 ? (): ('less')),'more');my$pager;while (@pagers){$pager=shift@pagers;next unless$pager;$pager=$self->which($pager);next unless$pager;last}if ($pager){system("$pager < $self->{log}")}else {$self->diag_fail("You don't seem to have a PAGER :/")}}sub chdir {my$self=shift;Cwd::chdir(File::Spec->canonpath($_[0]))or die "$_[0]: $!"}sub configure_mirrors {my$self=shift;unless (@{$self->{mirrors}}){$self->{mirrors}=['http://www.cpan.org' ]}for (@{$self->{mirrors}}){s!^/!file:///!;s!/$!!}}sub self_upgrade {my$self=shift;$self->check_upgrade;$self->{argv}=['App::cpanminus' ];return}sub install_module {my($self,$module,$depth,$version)=@_;$self->check_libs;if ($self->{seen}{$module}++){$self->chat("Already tried $module. Skipping.\n");return 1}if ($self->{skip_satisfied}){my($ok,$local)=$self->check_module($module,$version || 0);if ($ok){$self->diag("You have $module ($local)\n",1);return 1}}my$dist=$self->resolve_name($module,$version);unless ($dist){my$what=$module .($version ? " ($version)" : "");$self->diag_fail("Couldn't find module or a distribution $what",1);return}if ($dist->{distvname}&& $self->{seen}{$dist->{distvname}}++){$self->chat("Already tried $dist->{distvname}. Skipping.\n");return 1}if ($self->{cmd}eq 'info'){print$self->format_dist($dist),"\n";return 1}$dist->{depth}=$depth;if ($dist->{module}){unless ($self->satisfy_version($dist->{module},$dist->{module_version},$version)){$self->diag("Found $dist->{module} $dist->{module_version} which doesn't satisfy $version.\n",1);return}my$cmp=$version ? "==" : "";my$requirement=$dist->{module_version}? "$cmp$dist->{module_version}" : 0;my($ok,$local)=$self->check_module($dist->{module},$requirement);if ($self->{skip_installed}&& $ok){$self->diag("$dist->{module} is up to date. ($local)\n",1);return 1}}if ($dist->{dist}eq 'perl'){$self->diag("skipping $dist->{pathname}\n");return 1}$self->diag("--> Working on $module\n");$dist->{dir}||=$self->fetch_module($dist);unless ($dist->{dir}){$self->diag_fail("Failed to fetch distribution $dist->{distvname}",1);return}$self->chat("Entering $dist->{dir}\n");$self->chdir($self->{base});$self->chdir($dist->{dir});if ($self->{cmd}eq 'look'){$self->look;return 1}return$self->build_stuff($module,$dist,$depth)}sub uninstall_search_path {my$self=shift;$self->{local_lib}? (local::lib->install_base_arch_path($self->{local_lib}),local::lib->install_base_perl_path($self->{local_lib})): @Config{qw(installsitearch installsitelib)}}sub uninstall_module {my ($self,$module)=@_;$self->check_libs;my@inc=$self->uninstall_search_path;my($metadata,$packlist)=$self->packlists_containing($module,\@inc);unless ($packlist){$self->diag_fail(<<DIAG,1);return}my@uninst_files=$self->uninstall_target($metadata,$packlist);$self->ask_permission($module,\@uninst_files)or return;$self->uninstall_files(@uninst_files,$packlist);$self->diag("Successfully uninstalled $module\n",1);return 1}sub packlists_containing {my($self,$module,$inc)=@_;require Module::Metadata;my$metadata=Module::Metadata->new_from_module($module,inc=>$inc)or return;my$packlist;my$wanted=sub {return unless $_ eq '.packlist' && -f $_;for my$file ($self->unpack_packlist($File::Find::name)){$packlist ||=$File::Find::name if$file eq $metadata->filename}};{require File::pushd;my$pushd=File::pushd::pushd();my@search=grep -d $_,map File::Spec->catdir($_,'auto'),@$inc;File::Find::find($wanted,@search)}return$metadata,$packlist}sub uninstall_target {my($self,$metadata,$packlist)=@_;if ($self->has_shadow_install($metadata)or $self->{local_lib}){grep$self->should_unlink($_),$self->unpack_packlist($packlist)}else {$self->unpack_packlist($packlist)}}sub has_shadow_install {my($self,$metadata)=@_;my@shadow=grep defined,map Module::Metadata->new_from_module($metadata->name,inc=>[$_]),@INC;@shadow >= 2}sub should_unlink {my($self,$file)=@_;if ($self->{local_lib}){$file =~ /^\Q$self->{local_lib}\E/}else {!(grep$file =~ /^\Q$_\E/,@Config{qw(installbin installscript installman1dir installman3dir)})}}sub ask_permission {my ($self,$module,$files)=@_;$self->diag("$module contains the following files:\n\n");for my$file (@$files){$self->diag("  $file\n")}$self->diag("\n");return 'force uninstall' if$self->{force};local$self->{prompt}=1;return$self->prompt_bool("Are you sure you want to uninstall $module?",'y')}sub unpack_packlist {my ($self,$packlist)=@_;open my$fh,'<',$packlist or die "$packlist: $!";map {chomp;$_}<$fh>}sub uninstall_files {my ($self,@files)=@_;$self->diag("\n");for my$file (@files){$self->diag("Unlink: $file\n");unlink$file or $self->diag_fail("$!: $file")}$self->diag("\n");return 1}sub format_dist {my($self,$dist)=@_;return "$dist->{cpanid}/$dist->{filename}"}sub trim {local $_=shift;tr/\n/ /d;s/^\s*|\s*$//g;$_}sub fetch_module {my($self,$dist)=@_;$self->chdir($self->{base});for my$uri (@{$dist->{uris}}){$self->mask_output(diag_progress=>"Fetching $uri");my$filename=$dist->{filename}|| $uri;my$name=File::Basename::basename($filename);my$cancelled;my$fetch=sub {my$file;eval {local$SIG{INT}=sub {$cancelled=1;die "SIGINT\n"};$self->mirror($uri,$name);$file=$name if -e $name};$self->diag("ERROR: " .trim("$@")."\n",1)if $@ && $@ ne "SIGINT\n";return$file};my($try,$file);while ($try++ < 3){$file=$fetch->();last if$cancelled or $file;$self->diag_fail("Download $uri failed. Retrying ... ")}if ($cancelled){$self->diag_fail("Download cancelled.");return}unless ($file){$self->diag_fail("Failed to download $uri");next}$self->diag_ok;$dist->{local_path}=File::Spec->rel2abs($name);my$dir=$self->unpack($file,$uri,$dist);next unless$dir;if (my$save=$self->{save_dists}){my$path=$dist->{pathname}? "$save/authors/id/$dist->{pathname}" : "$save/vendor/$file";$self->chat("Copying $name to $path\n");File::Path::mkpath([File::Basename::dirname($path)],0,0777);File::Copy::copy($file,$path)or warn $!}return$dist,$dir}}sub unpack {my($self,$file,$uri,$dist)=@_;if ($self->{verify}){$self->verify_archive($file,$uri,$dist)or return}$self->chat("Unpacking $file\n");my$dir=$file =~ /\.zip/i ? $self->unzip($file): $self->untar($file);unless ($dir){$self->diag_fail("Failed to unpack $file: no directory")}return$dir}sub verify_checksums_signature {my($self,$chk_file)=@_;require Module::Signature;$self->chat("Verifying the signature of CHECKSUMS\n");my$rv=eval {local$SIG{__WARN__}=sub {};my$v=Module::Signature::_verify($chk_file);$v==Module::Signature::SIGNATURE_OK()};if ($rv){$self->chat("Verified OK!\n")}else {$self->diag_fail("Verifying CHECKSUMS signature failed: $rv\n");return}return 1}sub verify_archive {my($self,$file,$uri,$dist)=@_;unless ($dist->{cpanid}){$self->chat("Archive '$file' does not seem to be from PAUSE. Skip verification.\n")}(my$mirror=$uri)=~ s!/authors/id.*$!!;(my$chksum_uri=$uri)=~ s!/[^/]*$!/CHECKSUMS!;my$chk_file=$self->source_for($mirror)."/$dist->{cpanid}.CHECKSUMS";$self->mask_output(diag_progress=>"Fetching $chksum_uri");$self->mirror($chksum_uri,$chk_file);unless (-e $chk_file){$self->diag_fail("Fetching $chksum_uri failed.\n");return}$self->diag_ok;$self->verify_checksums_signature($chk_file)or return;$self->verify_checksum($file,$chk_file)}sub verify_checksum {my($self,$file,$chk_file)=@_;$self->chat("Verifying the SHA1 for $file\n");open my$fh,"<$chk_file" or die "$chk_file: $!";my$data=join '',<$fh>;$data =~ s/\015?\012/\n/g;require Safe;my$chksum=Safe->new->reval($data);if (!ref$chksum or ref$chksum ne 'HASH'){$self->diag_fail("! Checksum file downloaded from $chk_file is broken.\n");return}if (my$sha=$chksum->{$file}{sha256}){my$hex=$self->sha1_for($file);if ($hex eq $sha){$self->chat("Checksum for $file: Verified!\n")}else {$self->diag_fail("Checksum mismatch for $file\n");return}}else {$self->chat("Checksum for $file not found in CHECKSUMS.\n");return}}sub sha1_for {my($self,$file)=@_;require Digest::SHA;open my$fh,"<",$file or die "$file: $!";my$dg=Digest::SHA->new(256);my($data);while (read($fh,$data,4096)){$dg->add($data)}return$dg->hexdigest}sub verify_signature {my($self,$dist)=@_;$self->diag_progress("Verifying the SIGNATURE file");my$out=`$self->{cpansign} -v --skip 2>&1`;$self->log($out);if ($out =~ /Signature verified OK/){$self->diag_ok("Verified OK");return 1}else {$self->diag_fail("SIGNATURE verificaion for $dist->{filename} failed\n");return}}sub resolve_name {my($self,$module,$version)=@_;if ($module =~ /^(ftp|https?|file):/){if ($module =~ m!authors/id/(.*)!){return$self->cpan_dist($1,$module)}else {return {uris=>[$module ]}}}if ($module =~ m!^[\./]! && -d $module){return {source=>'local',dir=>Cwd::abs_path($module),}}if (-f $module){return {source=>'local',uris=>["file://" .Cwd::abs_path($module)],}}if ($module =~ /(?:^git:|\.git(?:@.+)?$)/){return$self->git_uri($module)}if ($module =~ s!^cpan:///distfile/!!){return$self->cpan_dist($module)}if ($module =~ m!^(?:[A-Z]/[A-Z]{2}/)?([A-Z]{2}[\-A-Z0-9]*/.*)$!){return$self->cpan_dist($1)}return$self->search_module($module,$version)}sub cpan_module {my($self,$module,$dist,$version)=@_;my$dist=$self->cpan_dist($dist);$dist->{module}=$module;$dist->{module_version}=$version if$version && $version ne 'undef';return$dist}sub cpan_dist {my($self,$dist,$url)=@_;$dist =~ s!^([A-Z]{2})!substr($1,0,1)."/".substr($1,0,2)."/".$1!e;require CPAN::DistnameInfo;my$d=CPAN::DistnameInfo->new($dist);if ($url){$url=[$url ]unless ref$url eq 'ARRAY'}else {my$id=$d->cpanid;my$fn=substr($id,0,1)."/" .substr($id,0,2)."/" .$id ."/" .$d->filename;my@mirrors=@{$self->{mirrors}};my@urls=map "$_/authors/id/$fn",@mirrors;$url=\@urls,}return {$d->properties,source=>'cpan',uris=>$url,}}sub git_uri {my ($self,$uri)=@_;($uri,my$commitish)=split /(?<=\.git)@/i,$uri,2;my$dir=File::Temp::tempdir(CLEANUP=>1);$self->mask_output(diag_progress=>"Cloning $uri");$self->run(['git','clone',$uri,$dir ]);unless (-e "$dir/.git"){$self->diag_fail("Failed cloning git repository $uri",1);return}if ($commitish){require File::pushd;my$dir=File::pushd::pushd($dir);unless ($self->run(['git','checkout',$commitish ])){$self->diag_fail("Failed to checkout '$commitish' in git repository $uri\n");return}}$self->diag_ok;return {source=>'local',dir=>$dir,}}sub setup_module_build_patch {my$self=shift;open my$out,">$self->{base}/ModuleBuildSkipMan.pm" or die $!;print$out <<EOF}sub core_version_for {my($self,$module)=@_;require Module::CoreList;unless (exists$Module::CoreList::version{$]+0}){die sprintf("Module::CoreList %s (loaded from %s) doesn't seem to have entries for perl $]. " ."You're strongly recommended to upgrade Module::CoreList from CPAN.\n",$Module::CoreList::VERSION,$INC{"Module/CoreList.pm"})}unless (exists$Module::CoreList::version{$]+0}{$module}){return -1}return$Module::CoreList::version{$]+0}{$module}}sub check_module {my($self,$mod,$want_ver)=@_;require Module::Metadata;my$meta=Module::Metadata->new_from_module($mod,inc=>$self->{search_inc})or return 0,undef;my$version=$meta->version;if ($self->{self_contained}&& $self->loaded_from_perl_lib($meta)){$version=$self->core_version_for($mod);return 0,undef if$version && $version==-1}$self->{local_versions}{$mod}=$version;if ($self->is_deprecated($meta)){return 0,$version}elsif ($self->satisfy_version($mod,$version,$want_ver)){return 1,($version || 'undef')}else {return 0,$version}}sub satisfy_version {my($self,$mod,$version,$want_ver)=@_;$want_ver='0' unless defined($want_ver)&& length($want_ver);require CPAN::Meta::Requirements;my$requirements=CPAN::Meta::Requirements->new;$requirements->add_string_requirement($mod,$want_ver);$requirements->accepts_module($mod,$version)}sub unsatisfy_how {my($self,$ver,$want_ver)=@_;if ($want_ver =~ /^[v0-9\.\_]+$/){return "$ver < $want_ver"}else {return "$ver doesn't satisfy $want_ver"}}sub is_deprecated {my($self,$meta)=@_;my$deprecated=eval {require Module::CoreList;Module::CoreList::is_deprecated($meta->{module})};return$deprecated && $self->loaded_from_perl_lib($meta)}sub loaded_from_perl_lib {my($self,$meta)=@_;require Config;for my$dir (qw(archlibexp privlibexp)){my$confdir=$Config{$dir};if ($confdir eq substr($meta->filename,0,length($confdir))){return 1}}return}sub should_install {my($self,$mod,$ver)=@_;$self->chat("Checking if you have $mod $ver ... ");my($ok,$local)=$self->check_module($mod,$ver);if ($ok){$self->chat("Yes ($local)\n")}elsif ($local){$self->chat("No (" .$self->unsatisfy_how($local,$ver).")\n")}else {$self->chat("No\n")}return$mod unless$ok;return}sub check_perl_version {my($self,$version)=@_;require CPAN::Meta::Requirements;my$req=CPAN::Meta::Requirements->from_string_hash({perl=>$version });$req->accepts_module(perl=>$])}sub install_deps {my($self,$dir,$depth,@deps)=@_;my(@install,%seen,@fail);for my$dep (@deps){next if$seen{$dep->module};if ($dep->module eq 'perl'){if ($dep->is_requirement &&!$self->check_perl_version($dep->version)){$self->diag("Needs perl @{[$dep->version]}, you have $]\n");push@fail,'perl'}}elsif ($self->should_install($dep->module,$dep->version)){push@install,$dep;$seen{$dep->module}=1}}if (@install){$self->diag("==> Found dependencies: " .join(", ",map $_->module,@install)."\n")}for my$dep (@install){$self->install_module($dep->module,$depth + 1,$dep->version)}$self->chdir($self->{base});$self->chdir($dir)if$dir;if ($self->{scandeps}){return 1}my@not_ok=$self->unsatisfied_deps(@deps);if (@not_ok){return 0,\@not_ok}else {return 1}}sub unsatisfied_deps {my($self,@deps)=@_;require CPAN::Meta::Check;require CPAN::Meta::Requirements;my$reqs=CPAN::Meta::Requirements->new;for my$dep (grep $_->is_requirement,@deps){$reqs->add_string_requirement($dep->module=>$dep->version || '0')}my$ret=CPAN::Meta::Check::check_requirements($reqs,'requires',$self->{search_inc});grep defined,values %$ret}sub install_deps_bailout {my($self,$target,$dir,$depth,@deps)=@_;my($ok,$fail)=$self->install_deps($dir,$depth,@deps);if (!$ok){$self->diag_fail("Installing the dependencies failed: " .join(", ",@$fail),1);unless ($self->prompt_bool("Do you want to continue building $target anyway?","n")){$self->diag_fail("Bailing out the installation for $target.",1);return}}return 1}sub build_stuff {my($self,$stuff,$dist,$depth)=@_;if ($self->{verify}&& -e 'SIGNATURE'){$self->verify_signature($dist)or return}require CPAN::Meta;my($meta_file)=grep -f,qw(META.json META.yml);if ($meta_file){$self->chat("Checking configure dependencies from $meta_file\n");$dist->{cpanmeta}=eval {CPAN::Meta->load_file($meta_file)}}elsif ($dist->{dist}&& $dist->{version}){$self->chat("META.yml/json not found. Creating skeleton for it.\n");$dist->{cpanmeta}=CPAN::Meta->new({name=>$dist->{dist},version=>$dist->{version}})}$dist->{meta}=$dist->{cpanmeta}? $dist->{cpanmeta}->as_struct : {};my@config_deps;if ($dist->{cpanmeta}){push@config_deps,Dependency->from_prereqs($dist->{cpanmeta}->effective_prereqs,['configure'],$self->{install_types},)}else {push@config_deps,Dependency->from_versions($dist->{meta}{configure_requires}|| {},'configure',)}if (-e 'Build.PL' &&!$self->should_use_mm($dist->{dist})){push@config_deps,Dependency->from_versions({'Module::Build'=>'0.36' },'configure',)}my$target=$dist->{meta}{name}? "$dist->{meta}{name}-$dist->{meta}{version}" : $dist->{dir};$self->install_deps_bailout($target,$dist->{dir},$depth,@config_deps)or return;$self->diag_progress("Configuring $target");my$configure_state=$self->configure_this($dist,$depth);$self->diag_ok($configure_state->{configured_ok}? "OK" : "N/A");$dist->{provides}=$self->extract_packages($dist->{cpanmeta},".")if$dist->{cpanmeta}&& $dist->{source}eq 'cpan';my$root_target=(($self->{installdeps}or $self->{showdeps})and $depth==0);$dist->{want_phases}=$self->{notest}&&!$root_target ? [qw(build runtime)]: [qw(build test runtime)];push @{$dist->{want_phases}},'develop' if$self->{with_develop}&& $depth==0;my@deps=$self->find_prereqs($dist);my$module_name=$self->find_module_name($configure_state)|| $dist->{meta}{name};$module_name =~ s/-/::/g;if ($self->{showdeps}){for my$dep (@config_deps,@deps){print$dep->module,($dep->version ? ("~".$dep->version): ""),"\n"}return 1}my$distname=$dist->{meta}{name}? "$dist->{meta}{name}-$dist->{meta}{version}" : $stuff;my$walkup;if ($self->{scandeps}){$walkup=$self->scandeps_append_child($dist)}$self->install_deps_bailout($distname,$dist->{dir},$depth,@deps)or return;if ($self->{scandeps}){unless ($configure_state->{configured_ok}){my$diag=<<DIAG;if (@config_deps){my@tree=@{$self->{scandeps_tree}};$diag .= "!\n" .join("",map "! * $_->[0]{module}\n",@tree[0..$#tree-1])if@tree}$self->diag("!\n$diag!\n",1)}$walkup->();return 1}if ($self->{installdeps}&& $depth==0){if ($configure_state->{configured_ok}){$self->diag("<== Installed dependencies for $stuff. Finishing.\n");return 1}else {$self->diag("! Configuring $distname failed. See $self->{log} for details.\n",1);return}}my$installed;if ($configure_state->{use_module_build}&& -e 'Build' && -f _){$self->diag_progress("Building " .($self->{notest}? "" : "and testing ").$distname);$self->build([$self->{perl},"./Build" ],$distname,$depth)&& $self->test([$self->{perl},"./Build","test" ],$distname,$depth)&& $self->install([$self->{perl},"./Build","install" ],["--uninst",1 ],$depth)&& $installed++}elsif ($self->{make}&& -e 'Makefile'){$self->diag_progress("Building " .($self->{notest}? "" : "and testing ").$distname);$self->build([$self->{make}],$distname,$depth)&& $self->test([$self->{make},"test" ],$distname,$depth)&& $self->install([$self->{make},"install" ],["UNINST=1" ],$depth)&& $installed++}else {my$why;my$configure_failed=$configure_state->{configured}&&!$configure_state->{configured_ok};if ($configure_failed){$why="Configure failed for $distname."}elsif ($self->{make}){$why="The distribution doesn't have a proper Makefile.PL/Build.PL"}else {$why="Can't configure the distribution. You probably need to have 'make'."}$self->diag_fail("$why See $self->{log} for details.",1);return}if ($installed && $self->{test_only}){$self->diag_ok;$self->diag("Successfully tested $distname\n",1)}elsif ($installed){my$local=$self->{local_versions}{$dist->{module}|| ''};my$version=$dist->{module_version}|| $dist->{meta}{version}|| $dist->{version};my$reinstall=$local && ($local eq $version);my$action=$local &&!$reinstall ? $self->numify_ver($version)< $self->numify_ver($local)? "downgraded" : "upgraded" : undef;my$how=$reinstall ? "reinstalled $distname" : $local ? "installed $distname ($action from $local)" : "installed $distname" ;my$msg="Successfully $how";$self->diag_ok;$self->diag("$msg\n",1);$self->{installed_dists}++;$self->save_meta($stuff,$dist,$module_name,\@config_deps,\@deps);return 1}else {my$what=$self->{test_only}? "Testing" : "Installing";$self->diag_fail("$what $stuff failed. See $self->{log} for details. Retry with --force to force install it.",1);return}}sub perl_requirements {my($self,@requires)=@_;my@perl;for my$requires (grep defined,@requires){if (exists$requires->{perl}){push@perl,Dependency->new(perl=>$requires->{perl})}}return@perl}sub should_use_mm {my($self,$dist)=@_;my%should_use_mm=map {$_=>1}qw(version ExtUtils-ParseXS ExtUtils-Install ExtUtils-Manifest);$should_use_mm{$dist}}sub configure_this {my($self,$dist,$depth)=@_;if (-e $self->{cpanfile_path}&& $self->{installdeps}&& $depth==0){require Module::CPANfile;$dist->{cpanfile}=eval {Module::CPANfile->load($self->{cpanfile_path})};$self->diag_fail($@,1)if $@;return {configured=>1,configured_ok=>!!$dist->{cpanfile},use_module_build=>0,}}if ($self->{skip_configure}){my$eumm=-e 'Makefile';my$mb=-e 'Build' && -f _;return {configured=>1,configured_ok=>$eumm || $mb,use_module_build=>$mb,}}my$state={};my$try_eumm=sub {if (-e 'Makefile.PL'){$self->chat("Running Makefile.PL\n");if ($self->configure([$self->{perl},"Makefile.PL" ],$depth)){$state->{configured_ok}=-e 'Makefile'}$state->{configured}++}};my$try_mb=sub {if (-e 'Build.PL'){$self->chat("Running Build.PL\n");if ($self->configure([$self->{perl},"Build.PL" ],$depth)){$state->{configured_ok}=-e 'Build' && -f _}$state->{use_module_build}++;$state->{configured}++}};my@try;if ($dist->{dist}&& $self->should_use_mm($dist->{dist})){@try=($try_eumm,$try_mb)}else {@try=($try_mb,$try_eumm)}for my$try (@try){$try->();last if$state->{configured_ok}}unless ($state->{configured_ok}){while (1){my$ans=lc$self->prompt("Configuring $dist->{dist} failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?","s");last if$ans eq 's';return$self->configure_this($dist,$depth)if$ans eq 'r';$self->show_build_log if$ans eq 'e';$self->look if$ans eq 'l'}}return$state}sub find_module_name {my($self,$state)=@_;return unless$state->{configured_ok};if ($state->{use_module_build}&& -e "_build/build_params"){my$params=do {open my$in,"_build/build_params";$self->safe_eval(join "",<$in>)};return eval {$params->[2]{module_name}}|| undef}elsif (-e "Makefile"){open my$mf,"Makefile";while (<$mf>){if (/^\#\s+NAME\s+=>\s+(.*)/){return$self->safe_eval($1)}}}return}sub list_files {my$self=shift;if (-e 'MANIFEST'){require ExtUtils::Manifest;my$manifest=eval {ExtUtils::Manifest::manifind()}|| {};return sort {lc$a cmp lc$b}keys %$manifest}else {require File::Find;my@files;my$finder=sub {my$name=$File::Find::name;$name =~ s!\.[/\\]!!;push@files,$name};File::Find::find($finder,".");return sort {lc$a cmp lc$b}@files}}sub extract_packages {my($self,$meta,$dir)=@_;my$try=sub {my$file=shift;return 1 unless$meta->{no_index};return 0 if grep {$file =~ m!^$_/!}@{$meta->{no_index}{directory}|| []};return 0 if grep {$file eq $_}@{$meta->{no_index}{file}|| []};return 1};require App::cpanminus::ParsePM;my@files=grep {/\.pm(?:\.PL)?$/ && $try->($_)}$self->list_files;my$provides={};for my$file (@files){my$parser=App::cpanminus::ParsePM->new($meta);my$packages=$parser->parse($file);while (my($package,$meta)=each %$packages){$provides->{$package}||={file=>$meta->{infile},($meta->{version}eq 'undef')? (): (version=>$meta->{version}),}}}return$provides}sub save_meta {my($self,$module,$dist,$module_name,$config_deps,$build_deps)=@_;return unless$dist->{distvname}&& $dist->{source}eq 'cpan';my$base=($ENV{PERL_MM_OPT}|| '')=~ /INSTALL_BASE=/ ? ($self->install_base($ENV{PERL_MM_OPT})."/lib/perl5"): $Config{sitelibexp};my$provides=$dist->{provides};File::Path::mkpath("blib/meta",0,0777);my$local={name=>$module_name,target=>$module,version=>exists$provides->{$module_name}? ($provides->{$module_name}{version}|| $dist->{version}): $dist->{version},dist=>$dist->{distvname},pathname=>$dist->{pathname},provides=>$provides,};require JSON::PP;open my$fh,">","blib/meta/install.json" or die $!;print$fh JSON::PP::encode_json($local);if (-e "MYMETA.json"){File::Copy::copy("MYMETA.json","blib/meta/MYMETA.json")}my@cmd=(($self->{sudo}? 'sudo' : ()),$^X,'-MExtUtils::Install=install','-e',qq[install({ 'blib/meta' => '$base/$Config{archname}/.meta/$dist->{distvname}' })],);$self->run(\@cmd)}sub _merge_hashref {my($self,@hashrefs)=@_;my%hash;for my$h (@hashrefs){%hash=(%hash,%$h)}return \%hash}sub install_base {my($self,$mm_opt)=@_;$mm_opt =~ /INSTALL_BASE=(\S+)/ and return $1;die "Your PERL_MM_OPT doesn't contain INSTALL_BASE"}sub safe_eval {my($self,$code)=@_;eval$code}sub configure_features {my($self,$dist,@features)=@_;map $_->identifier,grep {$self->effective_feature($dist,$_)}@features}sub effective_feature {my($self,$dist,$feature)=@_;if ($dist->{depth}==0){my$value=$self->{features}{$feature->identifier};return$value if defined$value;return 1 if$self->{features}{__all}}if ($self->{interactive}){require CPAN::Meta::Requirements;$self->diag("[@{[ $feature->description ]}]\n",1);my$req=CPAN::Meta::Requirements->new;for my$phase (@{$dist->{want_phases}}){for my$type (@{$self->{install_types}}){$req->add_requirements($feature->prereqs->requirements_for($phase,$type))}}my$reqs=$req->as_string_hash;my@missing;for my$module (keys %$reqs){if ($self->should_install($module,$req->{$module})){push@missing,$module}}if (@missing){my$howmany=@missing;$self->diag("==> Found missing dependencies: " .join(", ",@missing)."\n",1);local$self->{prompt}=1;return$self->prompt_bool("Install the $howmany optional module(s)?","y")}}return}sub find_prereqs {my($self,$dist)=@_;my@deps=$self->extract_meta_prereqs($dist);if ($dist->{module}=~ /^Bundle::/i){push@deps,$self->bundle_deps($dist)}return@deps}sub extract_meta_prereqs {my($self,$dist)=@_;if ($dist->{cpanfile}){my@features=$self->configure_features($dist,$dist->{cpanfile}->features);my$prereqs=$dist->{cpanfile}->prereqs_with(@features);return Dependency->from_prereqs($prereqs,$dist->{want_phases},$self->{install_types})}my$meta=$dist->{meta};my@deps;if (-e "MYMETA.json"){require JSON::PP;$self->chat("Checking dependencies from MYMETA.json ...\n");my$json=do {open my$in,"<MYMETA.json";local $/;<$in>};my$mymeta=JSON::PP::decode_json($json);if ($mymeta){$meta->{$_}=$mymeta->{$_}for qw(name version);return$self->extract_prereqs($mymeta,$dist)}}if (-e 'MYMETA.yml'){$self->chat("Checking dependencies from MYMETA.yml ...\n");my$mymeta=$self->parse_meta('MYMETA.yml');if ($mymeta){$meta->{$_}=$mymeta->{$_}for qw(name version);return$self->extract_prereqs($mymeta,$dist)}}if (-e '_build/prereqs'){$self->chat("Checking dependencies from _build/prereqs ...\n");my$prereqs=do {open my$in,"_build/prereqs";$self->safe_eval(join "",<$in>)};@deps=$self->extract_prereqs({name=>$meta->{name},version=>$meta->{version},%$prereqs },$dist)}elsif (-e 'Makefile'){$self->chat("Finding PREREQ from Makefile ...\n");open my$mf,"Makefile";while (<$mf>){if (/^\#\s+PREREQ_PM => \{\s*(.*?)\s*\}/){my@all;my@pairs=split ', ',$1;for (@pairs){my ($pkg,$v)=split '=>',$_;push@all,[$pkg,$v ]}my$list=join ", ",map {"'$_->[0]' => $_->[1]"}@all;my$prereq=$self->safe_eval("no strict; +{ $list }");push@deps,Dependency->from_versions($prereq)if$prereq;last}}}return@deps}sub bundle_deps {my($self,$dist)=@_;my@files;File::Find::find({wanted=>sub {push@files,File::Spec->rel2abs($_)if /\.pm/i},no_chdir=>1,},'.');my@deps;for my$file (@files){open my$pod,"<",$file or next;my$in_contents;while (<$pod>){if (/^=head\d\s+CONTENTS/){$in_contents=1}elsif (/^=/){$in_contents=0}elsif ($in_contents){/^(\S+)\s*(\S+)?/ and push@deps,Dependency->new($1,$self->maybe_version($2))}}}return@deps}sub maybe_version {my($self,$string)=@_;return$string && $string =~ /^\.?\d/ ? $string : undef}sub extract_prereqs {my($self,$metadata,$dist)=@_;require CPAN::Meta;my$meta=CPAN::Meta->new($metadata,{lazy_validation=>1 });my@features=$self->configure_features($dist,$meta->features);return Dependency->from_prereqs($meta->effective_prereqs(\@features),$dist->{want_phases},$self->{install_types})}sub cleanup_workdirs {my$self=shift;my$expire=time - 24 * 60 * 60 * $self->{auto_cleanup};my@targets;opendir my$dh,"$self->{home}/work";while (my$e=readdir$dh){next if$e !~ /^(\d+)\.\d+$/;my$time=$1;if ($time < $expire){push@targets,"$self->{home}/work/$e"}}if (@targets){if (@targets >= 64){$self->diag("Expiring " .scalar(@targets)." work directories. This might take long...\n")}else {$self->chat("Expiring " .scalar(@targets)." work directories.\n")}File::Path::rmtree(\@targets,0,0)}}sub scandeps_append_child {my($self,$dist)=@_;my$new_node=[$dist,[]];my$curr_node=$self->{scandeps_current}|| [undef,$self->{scandeps_tree}];push @{$curr_node->[1]},$new_node;$self->{scandeps_current}=$new_node;return sub {$self->{scandeps_current}=$curr_node}}sub dump_scandeps {my$self=shift;if ($self->{format}eq 'tree'){$self->walk_down(sub {my($dist,$depth)=@_;if ($depth==0){print "$dist->{distvname}\n"}else {print " " x ($depth - 1);print "\\_ $dist->{distvname}\n"}},1)}elsif ($self->{format}=~ /^dists?$/){$self->walk_down(sub {my($dist,$depth)=@_;print$self->format_dist($dist),"\n"},0)}elsif ($self->{format}eq 'json'){require JSON::PP;print JSON::PP::encode_json($self->{scandeps_tree})}elsif ($self->{format}eq 'yaml'){require YAML;print YAML::Dump($self->{scandeps_tree})}else {$self->diag("Unknown format: $self->{format}\n")}}sub walk_down {my($self,$cb,$pre)=@_;$self->_do_walk_down($self->{scandeps_tree},$cb,0,$pre)}sub _do_walk_down {my($self,$children,$cb,$depth,$pre)=@_;for my$node (@$children){$cb->($node->[0],$depth)if$pre;$self->_do_walk_down($node->[1],$cb,$depth + 1,$pre);$cb->($node->[0],$depth)unless$pre}}sub DESTROY {my$self=shift;$self->{at_exit}->($self)if$self->{at_exit}}sub shell_quote {my($self,@stuff)=@_;if (WIN32){join ' ',map {/^${quote}.+${quote}$/ ? $_ : ($quote .$_ .$quote)}@stuff}else {String::ShellQuote::shell_quote_best_effort(@stuff)}}sub which {my($self,$name)=@_;return$name if File::Spec->file_name_is_absolute($name)&& -x $name;my$exe_ext=$Config{_exe};for my$dir (File::Spec->path){my$fullpath=File::Spec->catfile($dir,$name);if (-x $fullpath || -x ($fullpath .= $exe_ext)){if ($fullpath =~ /\s/){$fullpath=$self->shell_quote($fullpath)}return$fullpath}}return}sub get {my($self,$uri)=@_;if ($uri =~ /^file:/){$self->file_get($uri)}else {$self->{_backends}{get}->(@_)}}sub mirror {my($self,$uri,$local)=@_;if ($uri =~ /^file:/){$self->file_mirror($uri,$local)}else {$self->{_backends}{mirror}->(@_)}}sub untar {$_[0]->{_backends}{untar}->(@_)};sub unzip {$_[0]->{_backends}{unzip}->(@_)};sub uri_to_file {my($self,$uri)=@_;if ($uri =~ s!file:/+!!){$uri="/$uri" unless$uri =~ m![a-zA-Z]:!}return$uri}sub file_get {my($self,$uri)=@_;my$file=$self->uri_to_file($uri);open my$fh,"<$file" or return;join '',<$fh>}sub file_mirror {my($self,$uri,$path)=@_;my$file=$self->uri_to_file($uri);File::Copy::copy($file,$path)}sub has_working_lwp {my($self,$mirrors)=@_;my$https=grep /^https:/,@$mirrors;eval {require LWP::UserAgent;LWP::UserAgent->VERSION(5.802);require LWP::Protocol::https if$https;1}}sub init_tools {my$self=shift;return if$self->{initialized}++;if ($self->{make}=$self->which($Config{make})){$self->chat("You have make $self->{make}\n")}if ($self->{try_lwp}&& $self->has_working_lwp($self->{mirrors})){$self->chat("You have LWP $LWP::VERSION\n");my$ua=sub {LWP::UserAgent->new(parse_head=>0,env_proxy=>1,agent=>$self->agent,timeout=>30,@_,)};$self->{_backends}{get}=sub {my$self=shift;my$res=$ua->()->request(HTTP::Request->new(GET=>$_[0]));return unless$res->is_success;return$res->decoded_content};$self->{_backends}{mirror}=sub {my$self=shift;my$res=$ua->()->mirror(@_);die$res->content if$res->code==501;$res->code}}elsif ($self->{try_wget}and my$wget=$self->which('wget')){$self->chat("You have $wget\n");my@common=('--user-agent',$self->agent,'--retry-connrefused',($self->{verbose}? (): ('-q')),);$self->{_backends}{get}=sub {my($self,$uri)=@_;$self->safeexec(my$fh,$wget,$uri,@common,'-O','-')or die "wget $uri: $!";local $/;<$fh>};$self->{_backends}{mirror}=sub {my($self,$uri,$path)=@_;$self->safeexec(my$fh,$wget,$uri,@common,'-O',$path)or die "wget $uri: $!";local $/;<$fh>}}elsif ($self->{try_curl}and my$curl=$self->which('curl')){$self->chat("You have $curl\n");my@common=('--location','--user-agent',$self->agent,($self->{verbose}? (): '-s'),);$self->{_backends}{get}=sub {my($self,$uri)=@_;$self->safeexec(my$fh,$curl,@common,$uri)or die "curl $uri: $!";local $/;<$fh>};$self->{_backends}{mirror}=sub {my($self,$uri,$path)=@_;$self->safeexec(my$fh,$curl,@common,$uri,'-#','-o',$path)or die "curl $uri: $!";local $/;<$fh>}}else {require HTTP::Tiny;$self->chat("Falling back to HTTP::Tiny $HTTP::Tiny::VERSION\n");my%common=(agent=>$self->agent,);$self->{_backends}{get}=sub {my$self=shift;my$res=HTTP::Tiny->new(%common)->get($_[0]);return unless$res->{success};return$res->{content}};$self->{_backends}{mirror}=sub {my$self=shift;my$res=HTTP::Tiny->new(%common)->mirror(@_);return$res->{status}}}my$tar=$self->which('tar');my$tar_ver;my$maybe_bad_tar=sub {WIN32 || SUNOS || (($tar_ver=`$tar --version 2>/dev/null`)=~ /GNU.*1\.13/i)};if ($tar &&!$maybe_bad_tar->()){chomp$tar_ver;$self->chat("You have $tar: $tar_ver\n");$self->{_backends}{untar}=sub {my($self,$tarfile)=@_;my$xf=($self->{verbose}? 'v' : '')."xf";my$ar=$tarfile =~ /bz2$/ ? 'j' : 'z';my($root,@others)=`$tar ${ar}tf $tarfile` or return undef;FILE: {chomp$root;$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}system "$tar $ar$xf $tarfile";return$root if -d $root;$self->diag_fail("Bad archive: $tarfile");return undef}}elsif ($tar and my$gzip=$self->which('gzip')and my$bzip2=$self->which('bzip2')){$self->chat("You have $tar, $gzip and $bzip2\n");$self->{_backends}{untar}=sub {my($self,$tarfile)=@_;my$x="x" .($self->{verbose}? 'v' : '')."f -";my$ar=$tarfile =~ /bz2$/ ? $bzip2 : $gzip;my($root,@others)=`$ar -dc $tarfile | $tar tf -` or return undef;FILE: {chomp$root;$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}system "$ar -dc $tarfile | $tar $x";return$root if -d $root;$self->diag_fail("Bad archive: $tarfile");return undef}}elsif (eval {require Archive::Tar}){$self->chat("Falling back to Archive::Tar $Archive::Tar::VERSION\n");$self->{_backends}{untar}=sub {my$self=shift;my$t=Archive::Tar->new($_[0]);my($root,@others)=$t->list_files;FILE: {$root =~ s!^\./!!;$root =~ s{^(.+?)/.*$}{$1};if (!length($root)){$root=shift(@others);redo FILE if$root}}$t->extract;return -d $root ? $root : undef}}else {$self->{_backends}{untar}=sub {die "Failed to extract $_[1] - You need to have tar or Archive::Tar installed.\n"}}if (my$unzip=$self->which('unzip')){$self->chat("You have $unzip\n");$self->{_backends}{unzip}=sub {my($self,$zipfile)=@_;my$opt=$self->{verbose}? '' : '-q';my(undef,$root,@others)=`$unzip -t $zipfile` or return undef;chomp$root;$root =~ s{^\s+testing:\s+([^/]+)/.*?\s+OK$}{$1};system "$unzip $opt $zipfile";return$root if -d $root;$self->diag_fail("Bad archive: [$root] $zipfile");return undef}}else {$self->{_backends}{unzip}=sub {eval {require Archive::Zip}or die "Failed to extract $_[1] - You need to have unzip or Archive::Zip installed.\n";my($self,$file)=@_;my$zip=Archive::Zip->new();my$status;$status=$zip->read($file);$self->diag_fail("Read of file[$file] failed")if$status!=Archive::Zip::AZ_OK();my@members=$zip->members();for my$member (@members){my$af=$member->fileName();next if ($af =~ m!^(/|\.\./)!);$status=$member->extractToFileNamed($af);$self->diag_fail("Extracting of file[$af] from zipfile[$file failed")if$status!=Archive::Zip::AZ_OK()}my ($root)=$zip->membersMatching(qr<^[^/]+/$>);$root &&=$root->fileName;return -d $root ? $root : undef}}}sub safeexec {my$self=shift;my$rdr=$_[0]||=Symbol::gensym();if (WIN32){my$cmd=$self->shell_quote(@_[1..$#_]);return open($rdr,"$cmd |")}if (my$pid=open($rdr,'-|')){return$pid}elsif (defined$pid){exec(@_[1 .. $#_ ]);exit 1}else {return}}sub mask_uri_passwords {my($self,@strings)=@_;s{ (https?://) ([^:/]+) : [^@/]+ @ }{$1$2:*password*@}gx for@strings;return@strings}sub parse_meta {my($self,$file)=@_;return eval {Parse::CPAN::Meta->load_file($file)}}sub parse_meta_string {my($self,$yaml)=@_;return eval {Parse::CPAN::Meta->load_yaml_string($yaml)}}package App::cpanminus::CommandExit;sub new {bless {code=>$_[1]},$_[0]}sub code {$_[0]->{code}}1;
   It appears your cpanm executable was installed via `perlbrew install-cpanm`.
   cpanm --self-upgrade won't upgrade the version of cpanm you're running.
   
@@ -162,7 +162,7 @@ $fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
   DIAG
 APP_CPANMINUS_SCRIPT
 
-$fatpacked{"CPAN/DistnameInfo.pm"} = <<'CPAN_DISTNAMEINFO';
+$fatpacked{"CPAN/DistnameInfo.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_DISTNAMEINFO';
   package CPAN::DistnameInfo;$VERSION="0.12";use strict;sub distname_info {my$file=shift or return;my ($dist,$version)=$file =~ /^
       ((?:[-+.]*(?:[A-Za-z0-9]+|(?<=\D)_|_(?=\D))*
        (?:
@@ -174,45 +174,45 @@ $fatpacked{"CPAN/DistnameInfo.pm"} = <<'CPAN_DISTNAMEINFO';
     $/xs or return ($file,undef,undef);if ($dist =~ /-undef\z/ and!length$version){$dist =~ s/-undef\z//}$version =~ s/-withoutworldwriteables$//;if ($version =~ /^(-[Vv].*)-(\d.*)/){$dist .= $1;$version=$2}if ($version =~ /(.+_.*)-(\d.*)/){$dist .= $1;$version=$2}$dist =~ s{\.pm$}{};$version=$1 if!length$version and $dist =~ s/-(\d+\w)$//;$version=$1 .$version if$version =~ /^\d+$/ and $dist =~ s/-(\w+)$//;if ($version =~ /\d\.\d/){$version =~ s/^[-_.]+//}else {$version =~ s/^[-_]+//}my$dev;if (length$version){if ($file =~ /^perl-?\d+\.(\d+)(?:\D(\d+))?(-(?:TRIAL|RC)\d+)?$/){$dev=1 if (($1 > 6 and $1 & 1)or ($2 and $2 >= 50))or $3}elsif ($version =~ /\d\D\d+_\d/ or $version =~ /-TRIAL/){$dev=1}}else {$version=undef}($dist,$version,$dev)}sub new {my$class=shift;my$distfile=shift;$distfile =~ s,//+,/,g;my%info=(pathname=>$distfile);($info{filename}=$distfile)=~ s,^(((.*?/)?authors/)?id/)?([A-Z])/(\4[A-Z])/(\5[-A-Z0-9]*)/,, and $info{cpanid}=$6;if ($distfile =~ m,([^/]+)\.(tar\.(?:g?z|bz2)|zip|tgz)$,i){$info{distvname}=$1;$info{extension}=$2}@info{qw(dist version beta)}=distname_info($info{distvname});$info{maturity}=delete$info{beta}? 'developer' : 'released';return bless \%info,$class}sub dist {shift->{dist}}sub version {shift->{version}}sub maturity {shift->{maturity}}sub filename {shift->{filename}}sub cpanid {shift->{cpanid}}sub distvname {shift->{distvname}}sub extension {shift->{extension}}sub pathname {shift->{pathname}}sub properties {%{$_[0]}}1;
 CPAN_DISTNAMEINFO
 
-$fatpacked{"CPAN/Meta.pm"} = <<'CPAN_META';
+$fatpacked{"CPAN/Meta.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META';
   use 5.006;use strict;use warnings;package CPAN::Meta;our$VERSION='2.132510';use Carp qw(carp croak);use CPAN::Meta::Feature;use CPAN::Meta::Prereqs;use CPAN::Meta::Converter;use CPAN::Meta::Validator;use Parse::CPAN::Meta 1.4403 ();BEGIN {*_dclone=\&CPAN::Meta::Converter::_dclone}BEGIN {my@STRING_READERS=qw(abstract description dynamic_config generated_by name release_status version);no strict 'refs';for my$attr (@STRING_READERS){*$attr=sub {$_[0]{$attr }}}}BEGIN {my@LIST_READERS=qw(author keywords license);no strict 'refs';for my$attr (@LIST_READERS){*$attr=sub {my$value=$_[0]{$attr };croak "$attr must be called in list context" unless wantarray;return @{_dclone($value)}if ref$value;return$value}}}sub authors {$_[0]->author}sub licenses {$_[0]->license}BEGIN {my@MAP_READERS=qw(meta-spec resources provides no_index prereqs optional_features);no strict 'refs';for my$attr (@MAP_READERS){(my$subname=$attr)=~ s/-/_/;*$subname=sub {my$value=$_[0]{$attr };return _dclone($value)if$value;return {}}}}sub custom_keys {return grep {/^x_/i}keys %{$_[0]}}sub custom {my ($self,$attr)=@_;my$value=$self->{$attr};return _dclone($value)if ref$value;return$value}sub _new {my ($class,$struct,$options)=@_;my$self;if ($options->{lazy_validation}){my$cmc=CPAN::Meta::Converter->new($struct);$self=$cmc->convert(version=>2);return bless$self,$class}else {my$cmv=CPAN::Meta::Validator->new($struct);unless ($cmv->is_valid){die "Invalid metadata structure. Errors: " .join(", ",$cmv->errors)."\n"}}my$version=$struct->{'meta-spec'}{version}|| '1.0';if ($version==2){$self=$struct}else {my$cmc=CPAN::Meta::Converter->new($struct);$self=$cmc->convert(version=>2)}return bless$self,$class}sub new {my ($class,$struct,$options)=@_;my$self=eval {$class->_new($struct,$options)};croak($@)if $@;return$self}sub create {my ($class,$struct,$options)=@_;my$version=__PACKAGE__->VERSION || 2;$struct->{generated_by}||=__PACKAGE__ ." version $version" ;$struct->{'meta-spec'}{version}||=int($version);my$self=eval {$class->_new($struct,$options)};croak ($@)if $@;return$self}sub load_file {my ($class,$file,$options)=@_;$options->{lazy_validation}=1 unless exists$options->{lazy_validation};croak "load_file() requires a valid, readable filename" unless -r $file;my$self;eval {my$struct=Parse::CPAN::Meta->load_file($file);$self=$class->_new($struct,$options)};croak($@)if $@;return$self}sub load_yaml_string {my ($class,$yaml,$options)=@_;$options->{lazy_validation}=1 unless exists$options->{lazy_validation};my$self;eval {my ($struct)=Parse::CPAN::Meta->load_yaml_string($yaml);$self=$class->_new($struct,$options)};croak($@)if $@;return$self}sub load_json_string {my ($class,$json,$options)=@_;$options->{lazy_validation}=1 unless exists$options->{lazy_validation};my$self;eval {my$struct=Parse::CPAN::Meta->load_json_string($json);$self=$class->_new($struct,$options)};croak($@)if $@;return$self}sub save {my ($self,$file,$options)=@_;my$version=$options->{version}|| '2';my$layer=$] ge '5.008001' ? ':utf8' : '';if ($version ge '2'){carp "'$file' should end in '.json'" unless$file =~ m{\.json$}}else {carp "'$file' should end in '.yml'" unless$file =~ m{\.yml$}}my$data=$self->as_string($options);open my$fh,">$layer",$file or die "Error opening '$file' for writing: $!\n";print {$fh}$data;close$fh or die "Error closing '$file': $!\n";return 1}sub meta_spec_version {my ($self)=@_;return$self->meta_spec->{version}}sub effective_prereqs {my ($self,$features)=@_;$features ||=[];my$prereq=CPAN::Meta::Prereqs->new($self->prereqs);return$prereq unless @$features;my@other=map {;$self->feature($_)->prereqs}@$features;return$prereq->with_merged_prereqs(\@other)}sub should_index_file {my ($self,$filename)=@_;for my$no_index_file (@{$self->no_index->{file}|| []}){return if$filename eq $no_index_file}for my$no_index_dir (@{$self->no_index->{directory}}){$no_index_dir =~ s{$}{/} unless$no_index_dir =~ m{/\z};return if index($filename,$no_index_dir)==0}return 1}sub should_index_package {my ($self,$package)=@_;for my$no_index_pkg (@{$self->no_index->{package}|| []}){return if$package eq $no_index_pkg}for my$no_index_ns (@{$self->no_index->{namespace}}){return if index($package,"${no_index_ns}::")==0}return 1}sub features {my ($self)=@_;my$opt_f=$self->optional_features;my@features=map {;CPAN::Meta::Feature->new($_=>$opt_f->{$_ })}keys %$opt_f;return@features}sub feature {my ($self,$ident)=@_;croak "no feature named $ident" unless my$f=$self->optional_features->{$ident };return CPAN::Meta::Feature->new($ident,$f)}sub as_struct {my ($self,$options)=@_;my$struct=_dclone($self);if ($options->{version}){my$cmc=CPAN::Meta::Converter->new($struct);$struct=$cmc->convert(version=>$options->{version})}return$struct}sub as_string {my ($self,$options)=@_;my$version=$options->{version}|| '2';my$struct;if ($self->meta_spec_version ne $version){my$cmc=CPAN::Meta::Converter->new($self->as_struct);$struct=$cmc->convert(version=>$version)}else {$struct=$self->as_struct}my ($data,$backend);if ($version ge '2'){$backend=Parse::CPAN::Meta->json_backend();$data=$backend->new->pretty->canonical->encode($struct)}else {$backend=Parse::CPAN::Meta->yaml_backend();$data=eval {no strict 'refs';&{"$backend\::Dump"}($struct)};if ($@){croak$backend->can('errstr')? $backend->errstr : $@}}return$data}sub TO_JSON {return {%{$_[0]}}}1;
 CPAN_META
 
-$fatpacked{"CPAN/Meta/Check.pm"} = <<'CPAN_META_CHECK';
+$fatpacked{"CPAN/Meta/Check.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_CHECK';
   package CPAN::Meta::Check;{$CPAN::Meta::Check::VERSION='0.007'}use strict;use warnings;use Exporter 5.57 'import';our@EXPORT=qw//;our@EXPORT_OK=qw/check_requirements requirements_for verify_dependencies/;our%EXPORT_TAGS=(all=>[@EXPORT,@EXPORT_OK ]);use CPAN::Meta::Requirements 2.120920;use Module::Metadata;sub _check_dep {my ($reqs,$module,$dirs)=@_;my$version=$module eq 'perl' ? $] : do {my$metadata=Module::Metadata->new_from_module($module,inc=>$dirs);return "Module '$module' is not installed" if not defined$metadata;eval {$metadata->version}};return "Missing version info for module '$module'" if$reqs->requirements_for_module($module)and not $version;return sprintf 'Installed version (%s) of %s is not in range \'%s\'',$version,$module,$reqs->requirements_for_module($module)if not $reqs->accepts_module($module,$version || 0);return}sub _check_conflict {my ($reqs,$module,$dirs)=@_;my$metadata=Module::Metadata->new_from_module($module,inc=>$dirs);return if not defined$metadata;my$version=eval {$metadata->version};return "Missing version info for module '$module'" if not $version;return sprintf 'Installed version (%s) of %s is in range \'%s\'',$version,$module,$reqs->requirements_for_module($module)if$reqs->accepts_module($module,$version);return}sub requirements_for {my ($meta,$phases,$type)=@_;my$prereqs=ref($meta)eq 'CPAN::Meta' ? $meta->effective_prereqs : $meta;if (!ref$phases){return$prereqs->requirements_for($phases,$type)}else {my$ret=CPAN::Meta::Requirements->new;for my$phase (@{$phases}){$ret->add_requirements($prereqs->requirements_for($phase,$type))}return$ret}}sub check_requirements {my ($reqs,$type,$dirs)=@_;my%ret;if ($type ne 'conflicts'){for my$module ($reqs->required_modules){$ret{$module}=_check_dep($reqs,$module,$dirs)}}else {for my$module ($reqs->required_modules){$ret{$module}=_check_conflict($reqs,$module,$dirs)}}return \%ret}sub verify_dependencies {my ($meta,$phases,$type,$dirs)=@_;my$reqs=requirements_for($meta,$phases,$type);my$issues=check_requirements($reqs,$type,$dirs);return grep {defined}values %{$issues}}1;
 CPAN_META_CHECK
 
-$fatpacked{"CPAN/Meta/Converter.pm"} = <<'CPAN_META_CONVERTER';
+$fatpacked{"CPAN/Meta/Converter.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_CONVERTER';
   use 5.006;use strict;use warnings;package CPAN::Meta::Converter;our$VERSION='2.132510';use CPAN::Meta::Validator;use CPAN::Meta::Requirements;use version 0.88 ();use Parse::CPAN::Meta 1.4400 ();sub _dclone {my$ref=shift;no warnings 'once';local*UNIVERSAL::TO_JSON=sub {return "$_[0]"};my$backend=Parse::CPAN::Meta->json_backend();return$backend->new->utf8->decode($backend->new->utf8->allow_blessed->convert_blessed->encode($ref))}my%known_specs=('2'=>'http://search.cpan.org/perldoc?CPAN::Meta::Spec','1.4'=>'http://module-build.sourceforge.net/META-spec-v1.4.html','1.3'=>'http://module-build.sourceforge.net/META-spec-v1.3.html','1.2'=>'http://module-build.sourceforge.net/META-spec-v1.2.html','1.1'=>'http://module-build.sourceforge.net/META-spec-v1.1.html','1.0'=>'http://module-build.sourceforge.net/META-spec-v1.0.html');my@spec_list=sort {$a <=> $b}keys%known_specs;my ($LOWEST,$HIGHEST)=@spec_list[0,-1];sub _keep {$_[0]}sub _keep_or_one {defined($_[0])? $_[0]: 1}sub _keep_or_zero {defined($_[0])? $_[0]: 0}sub _keep_or_unknown {defined($_[0])&& length($_[0])? $_[0]: "unknown"}sub _generated_by {my$gen=shift;my$sig=__PACKAGE__ ." version " .(__PACKAGE__->VERSION || "<dev>");return$sig unless defined$gen and length$gen;return$gen if$gen =~ /(, )\Q$sig/;return "$gen, $sig"}sub _listify {!defined $_[0]? undef : ref $_[0]eq 'ARRAY' ? $_[0]: [$_[0]]}sub _prefix_custom {my$key=shift;$key =~ s/^(?!x_)   # Unless it already starts with x_
                (?:x-?)? # Remove leading x- or x (if present)
              /x_/ix;return$key}sub _ucfirst_custom {my$key=shift;$key=ucfirst$key unless$key =~ /[A-Z]/;return$key}sub _no_prefix_ucfirst_custom {my$key=shift;$key =~ s/^x_//;return _ucfirst_custom($key)}sub _change_meta_spec {my ($element,undef,undef,$version)=@_;$element->{version}=$version;$element->{url}=$known_specs{$version};return$element}my@valid_licenses_1=('perl','gpl','apache','artistic','artistic_2','lgpl','bsd','gpl','mit','mozilla','open_source','unrestricted','restrictive','unknown',);my%license_map_1=((map {$_=>$_}@valid_licenses_1),artistic2=>'artistic_2',);sub _license_1 {my ($element)=@_;return 'unknown' unless defined$element;if ($license_map_1{lc$element}){return$license_map_1{lc$element}}return 'unknown'}my@valid_licenses_2=qw(agpl_3 apache_1_1 apache_2_0 artistic_1 artistic_2 bsd freebsd gfdl_1_2 gfdl_1_3 gpl_1 gpl_2 gpl_3 lgpl_2_1 lgpl_3_0 mit mozilla_1_0 mozilla_1_1 openssl perl_5 qpl_1_0 ssleay sun zlib open_source restricted unrestricted unknown);my%license_map_2=((map {$_=>$_}@valid_licenses_2),apache=>'apache_2_0',artistic=>'artistic_1',artistic2=>'artistic_2',gpl=>'open_source',lgpl=>'open_source',mozilla=>'open_source',perl=>'perl_5',restrictive=>'restricted',);sub _license_2 {my ($element)=@_;return ['unknown' ]unless defined$element;$element=[$element ]unless ref$element eq 'ARRAY';my@new_list;for my$lic (@$element){next unless defined$lic;if (my$new=$license_map_2{lc$lic}){push@new_list,$new}}return@new_list ? \@new_list : ['unknown' ]}my%license_downgrade_map=qw(agpl_3 open_source apache_1_1 apache apache_2_0 apache artistic_1 artistic artistic_2 artistic_2 bsd bsd freebsd open_source gfdl_1_2 open_source gfdl_1_3 open_source gpl_1 gpl gpl_2 gpl gpl_3 gpl lgpl_2_1 lgpl lgpl_3_0 lgpl mit mit mozilla_1_0 mozilla mozilla_1_1 mozilla openssl open_source perl_5 perl qpl_1_0 open_source ssleay open_source sun open_source zlib open_source open_source open_source restricted restrictive unrestricted unrestricted unknown unknown);sub _downgrade_license {my ($element)=@_;if (!defined$element){return "unknown"}elsif(ref$element eq 'ARRAY'){if (@$element==1){return$license_downgrade_map{$element->[0]}|| "unknown"}}elsif (!ref$element){return$license_downgrade_map{$element}|| "unknown"}return "unknown"}my$no_index_spec_1_2={'file'=>\&_listify,'dir'=>\&_listify,'package'=>\&_listify,'namespace'=>\&_listify,};my$no_index_spec_1_3={'file'=>\&_listify,'directory'=>\&_listify,'package'=>\&_listify,'namespace'=>\&_listify,};my$no_index_spec_2={'file'=>\&_listify,'directory'=>\&_listify,'package'=>\&_listify,'namespace'=>\&_listify,':custom'=>\&_prefix_custom,};sub _no_index_1_2 {my (undef,undef,$meta)=@_;my$no_index=$meta->{no_index}|| $meta->{private};return unless$no_index;if (!ref$no_index){my$item=$no_index;$no_index={dir=>[$item ],file=>[$item ]}}elsif (ref$no_index eq 'ARRAY'){my$list=$no_index;$no_index={dir=>[@$list ],file=>[@$list ]}}if (exists$no_index->{files}){$no_index->{file}=delete$no_index->{file}}if (exists$no_index->{modules}){$no_index->{module}=delete$no_index->{module}}return _convert($no_index,$no_index_spec_1_2)}sub _no_index_directory {my ($element,$key,$meta,$version)=@_;return unless$element;if (!ref$element){my$item=$element;$element={directory=>[$item ],file=>[$item ]}}elsif (ref$element eq 'ARRAY'){my$list=$element;$element={directory=>[@$list ],file=>[@$list ]}}if (exists$element->{dir}){$element->{directory}=delete$element->{dir}}if (exists$element->{files}){$element->{file}=delete$element->{file}}if (exists$element->{modules}){$element->{module}=delete$element->{module}}my$spec=$version==2 ? $no_index_spec_2 : $no_index_spec_1_3;return _convert($element,$spec)}sub _is_module_name {my$mod=shift;return unless defined$mod && length$mod;return$mod =~ m{^[A-Za-z][A-Za-z0-9_]*(?:::[A-Za-z0-9_]+)*$}}sub _clean_version {my ($element)=@_;return 0 if!defined$element;$element =~ s{^\s*}{};$element =~ s{\s*$}{};$element =~ s{^\.}{0.};return 0 if!length$element;return 0 if ($element eq 'undef' || $element eq '<undef>');my$v=eval {version->new($element)};if (defined$v){return$v->is_qv ? $v->normal : $element}else {return 0}}sub _bad_version_hook {my ($v)=@_;$v =~ s{[a-z]+$}{};my$vobj=eval {version->parse($v)};return defined($vobj)? $vobj : version->parse(0)}sub _version_map {my ($element)=@_;return unless defined$element;if (ref$element eq 'HASH'){my$new_map=CPAN::Meta::Requirements->new({bad_version_hook=>sub {version->new(0)}});while (my ($k,$v)=each %$element){next unless _is_module_name($k);if (!defined($v)||!length($v)|| $v eq 'undef' || $v eq '<undef>'){$v=0}if (_is_module_name($v)&&!version::is_lax($v)){$new_map->add_minimum($k=>0);$new_map->add_minimum($v=>0)}$new_map->add_string_requirement($k=>$v)}return$new_map->as_string_hash}elsif (ref$element eq 'ARRAY'){my$hashref={map {$_=>0}@$element };return _version_map($hashref)}elsif (ref$element eq '' && length$element){return {$element=>0 }}return}sub _prereqs_from_1 {my (undef,undef,$meta)=@_;my$prereqs={};for my$phase (qw/build configure/){my$key="${phase}_requires";$prereqs->{$phase}{requires}=_version_map($meta->{$key})if$meta->{$key}}for my$rel (qw/requires recommends conflicts/){$prereqs->{runtime}{$rel}=_version_map($meta->{$rel})if$meta->{$rel}}return$prereqs}my$prereqs_spec={configure=>\&_prereqs_rel,build=>\&_prereqs_rel,test=>\&_prereqs_rel,runtime=>\&_prereqs_rel,develop=>\&_prereqs_rel,':custom'=>\&_prefix_custom,};my$relation_spec={requires=>\&_version_map,recommends=>\&_version_map,suggests=>\&_version_map,conflicts=>\&_version_map,':custom'=>\&_prefix_custom,};sub _cleanup_prereqs {my ($prereqs,$key,$meta,$to_version)=@_;return unless$prereqs && ref$prereqs eq 'HASH';return _convert($prereqs,$prereqs_spec,$to_version)}sub _prereqs_rel {my ($relation,$key,$meta,$to_version)=@_;return unless$relation && ref$relation eq 'HASH';return _convert($relation,$relation_spec,$to_version)}BEGIN {my@old_prereqs=qw(requires configure_requires recommends conflicts);for (@old_prereqs){my$sub="_get_$_";my ($phase,$type)=split qr/_/,$_;if (!defined$type){$type=$phase;$phase='runtime'}no strict 'refs';*{$sub}=sub {_extract_prereqs($_[2]->{prereqs},$phase,$type)}}}sub _get_build_requires {my ($data,$key,$meta)=@_;my$test_h=_extract_prereqs($_[2]->{prereqs},qw(test requires))|| {};my$build_h=_extract_prereqs($_[2]->{prereqs},qw(build requires))|| {};my$test_req=CPAN::Meta::Requirements->from_string_hash($test_h);my$build_req=CPAN::Meta::Requirements->from_string_hash($build_h);$test_req->add_requirements($build_req)->as_string_hash}sub _extract_prereqs {my ($prereqs,$phase,$type)=@_;return unless ref$prereqs eq 'HASH';return scalar _version_map($prereqs->{$phase}{$type})}sub _downgrade_optional_features {my (undef,undef,$meta)=@_;return unless exists$meta->{optional_features};my$origin=$meta->{optional_features};my$features={};for my$name (keys %$origin){$features->{$name}={description=>$origin->{$name}{description},requires=>_extract_prereqs($origin->{$name}{prereqs},'runtime','requires'),configure_requires=>_extract_prereqs($origin->{$name}{prereqs},'runtime','configure_requires'),build_requires=>_extract_prereqs($origin->{$name}{prereqs},'runtime','build_requires'),recommends=>_extract_prereqs($origin->{$name}{prereqs},'runtime','recommends'),conflicts=>_extract_prereqs($origin->{$name}{prereqs},'runtime','conflicts'),};for my$k (keys %{$features->{$name}}){delete$features->{$name}{$k}unless defined$features->{$name}{$k}}}return$features}sub _upgrade_optional_features {my (undef,undef,$meta)=@_;return unless exists$meta->{optional_features};my$origin=$meta->{optional_features};my$features={};for my$name (keys %$origin){$features->{$name}={description=>$origin->{$name}{description},prereqs=>_prereqs_from_1(undef,undef,$origin->{$name}),};delete$features->{$name}{prereqs}{configure}}return$features}my$optional_features_2_spec={description=>\&_keep,prereqs=>\&_cleanup_prereqs,':custom'=>\&_prefix_custom,};sub _feature_2 {my ($element,$key,$meta,$to_version)=@_;return unless$element && ref$element eq 'HASH';_convert($element,$optional_features_2_spec,$to_version)}sub _cleanup_optional_features_2 {my ($element,$key,$meta,$to_version)=@_;return unless$element && ref$element eq 'HASH';my$new_data={};for my$k (keys %$element){$new_data->{$k}=_feature_2($element->{$k},$k,$meta,$to_version)}return unless keys %$new_data;return$new_data}sub _optional_features_1_4 {my ($element)=@_;return unless$element;$element=_optional_features_as_map($element);for my$name (keys %$element){for my$drop (qw/requires_packages requires_os excluded_os/){delete$element->{$name}{$drop}}}return$element}sub _optional_features_as_map {my ($element)=@_;return unless$element;if (ref$element eq 'ARRAY'){my%map;for my$feature (@$element){my (@parts)=%$feature;$map{$parts[0]}=$parts[1]}$element=\%map}return$element}sub _is_urlish {defined $_[0]&& $_[0]=~ m{\A[-+.a-z0-9]+:.+}i}sub _url_or_drop {my ($element)=@_;return$element if _is_urlish($element);return}sub _url_list {my ($element)=@_;return unless$element;$element=_listify($element);$element=[grep {_is_urlish($_)}@$element ];return unless @$element;return$element}sub _author_list {my ($element)=@_;return ['unknown' ]unless$element;$element=_listify($element);$element=[map {defined $_ && length $_ ? $_ : 'unknown'}@$element ];return ['unknown' ]unless @$element;return$element}my$resource2_upgrade={license=>sub {return _is_urlish($_[0])? _listify($_[0]): undef},homepage=>\&_url_or_drop,bugtracker=>sub {my ($item)=@_;return unless$item;if ($item =~ m{^mailto:(.*)$}){return {mailto=>$1 }}elsif(_is_urlish($item)){return {web=>$item }}else {return}},repository=>sub {return _is_urlish($_[0])? {url=>$_[0]}: undef},':custom'=>\&_prefix_custom,};sub _upgrade_resources_2 {my (undef,undef,$meta,$version)=@_;return unless exists$meta->{resources};return _convert($meta->{resources},$resource2_upgrade)}my$bugtracker2_spec={web=>\&_url_or_drop,mailto=>\&_keep,':custom'=>\&_prefix_custom,};sub _repo_type {my ($element,$key,$meta,$to_version)=@_;return$element if defined$element;return unless exists$meta->{url};my$repo_url=$meta->{url};for my$type (qw/git svn/){return$type if$repo_url =~ m{\A$type}}return}my$repository2_spec={web=>\&_url_or_drop,url=>\&_url_or_drop,type=>\&_repo_type,':custom'=>\&_prefix_custom,};my$resources2_cleanup={license=>\&_url_list,homepage=>\&_url_or_drop,bugtracker=>sub {ref $_[0]? _convert($_[0],$bugtracker2_spec): undef},repository=>sub {my$data=shift;ref$data ? _convert($data,$repository2_spec): undef},':custom'=>\&_prefix_custom,};sub _cleanup_resources_2 {my ($resources,$key,$meta,$to_version)=@_;return unless$resources && ref$resources eq 'HASH';return _convert($resources,$resources2_cleanup,$to_version)}my$resource1_spec={license=>\&_url_or_drop,homepage=>\&_url_or_drop,bugtracker=>\&_url_or_drop,repository=>\&_url_or_drop,':custom'=>\&_keep,};sub _resources_1_3 {my (undef,undef,$meta,$version)=@_;return unless exists$meta->{resources};return _convert($meta->{resources},$resource1_spec)}*_resources_1_4=*_resources_1_3;sub _resources_1_2 {my (undef,undef,$meta)=@_;my$resources=$meta->{resources}|| {};if ($meta->{license_url}&&!$resources->{license}){$resources->{license}=$meta->license_url if _is_urlish($meta->{license_url})}return unless keys %$resources;return _convert($resources,$resource1_spec)}my$resource_downgrade_spec={license=>sub {return ref $_[0]? $_[0]->[0]: $_[0]},homepage=>\&_url_or_drop,bugtracker=>sub {return $_[0]->{web}},repository=>sub {return $_[0]->{url}|| $_[0]->{web}},':custom'=>\&_no_prefix_ucfirst_custom,};sub _downgrade_resources {my (undef,undef,$meta,$version)=@_;return unless exists$meta->{resources};return _convert($meta->{resources},$resource_downgrade_spec)}sub _release_status {my ($element,undef,$meta)=@_;return$element if$element && $element =~ m{\A(?:stable|testing|unstable)\z};return _release_status_from_version(undef,undef,$meta)}sub _release_status_from_version {my (undef,undef,$meta)=@_;my$version=$meta->{version}|| '';return ($version =~ /_/)? 'testing' : 'stable'}my$provides_spec={file=>\&_keep,version=>\&_keep,};my$provides_spec_2={file=>\&_keep,version=>\&_keep,':custom'=>\&_prefix_custom,};sub _provides {my ($element,$key,$meta,$to_version)=@_;return unless defined$element && ref$element eq 'HASH';my$spec=$to_version==2 ? $provides_spec_2 : $provides_spec;my$new_data={};for my$k (keys %$element){$new_data->{$k}=_convert($element->{$k},$spec,$to_version);$new_data->{$k}{version}=_clean_version($element->{$k}{version})if exists$element->{$k}{version}}return$new_data}sub _convert {my ($data,$spec,$to_version)=@_;my$new_data={};for my$key (keys %$spec){next if$key eq ':custom' || $key eq ':drop';next unless my$fcn=$spec->{$key};die "spec for '$key' is not a coderef" unless ref$fcn && ref$fcn eq 'CODE';my$new_value=$fcn->($data->{$key},$key,$data,$to_version);$new_data->{$key}=$new_value if defined$new_value}my$drop_list=$spec->{':drop'};my$customizer=$spec->{':custom'}|| \&_keep;for my$key (keys %$data){next if$drop_list && grep {$key eq $_}@$drop_list;next if exists$spec->{$key};$new_data->{$customizer->($key)}=$data->{$key}}return$new_data}my%up_convert=('2-from-1.4'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_2,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'release_status'=>\&_release_status_from_version,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_upgrade_optional_features,'provides'=>\&_provides,'resources'=>\&_upgrade_resources_2,'description'=>\&_keep,'prereqs'=>\&_prereqs_from_1,':drop'=>[qw(build_requires configure_requires conflicts distribution_type license_url private recommends requires) ],':custom'=>\&_prefix_custom,},'1.4-from-1.3'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_optional_features_1_4,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_4,'configure_requires'=>\&_keep,':drop'=>[qw(license_url private)],':custom'=>\&_keep },'1.3-from-1.2'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_3,':drop'=>[qw(license_url private)],':custom'=>\&_keep },'1.2-from-1.1'=>{'version'=>\&_keep,'license'=>\&_license_1,'name'=>\&_keep,'generated_by'=>\&_generated_by,'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'meta-spec'=>\&_change_meta_spec,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'recommends'=>\&_version_map,'requires'=>\&_version_map,'keywords'=>\&_keep,'no_index'=>\&_no_index_1_2,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'resources'=>\&_resources_1_2,':drop'=>[qw(license_url private)],':custom'=>\&_keep },'1.1-from-1.0'=>{'version'=>\&_keep,'name'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'recommends'=>\&_version_map,'requires'=>\&_version_map,'license_url'=>\&_url_or_drop,'private'=>\&_keep,':custom'=>\&_keep },);my%down_convert=('1.4-from-2'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_downgrade_license,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_get_build_requires,'configure_requires'=>\&_get_configure_requires,'conflicts'=>\&_get_conflicts,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_downgrade_optional_features,'provides'=>\&_provides,'recommends'=>\&_get_recommends,'requires'=>\&_get_requires,'resources'=>\&_downgrade_resources,':drop'=>[qw(description prereqs release_status)],':custom'=>\&_keep },'1.3-from-1.4'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_3,':drop'=>[qw(configure_requires)],':custom'=>\&_keep,},'1.2-from-1.3'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_1_2,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_3,':custom'=>\&_keep,},'1.1-from-1.2'=>{'version'=>\&_keep,'name'=>\&_keep,'meta-spec'=>\&_change_meta_spec,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'private'=>\&_keep,'recommends'=>\&_version_map,'requires'=>\&_version_map,':drop'=>[qw(abstract author provides no_index keywords resources)],':custom'=>\&_keep,},'1.0-from-1.1'=>{'name'=>\&_keep,'meta-spec'=>\&_change_meta_spec,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'recommends'=>\&_version_map,'requires'=>\&_version_map,':custom'=>\&_keep,},);my%cleanup=('2'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_2,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'release_status'=>\&_release_status,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_cleanup_optional_features_2,'provides'=>\&_provides,'resources'=>\&_cleanup_resources_2,'description'=>\&_keep,'prereqs'=>\&_cleanup_prereqs,':drop'=>[qw(build_requires configure_requires conflicts distribution_type license_url private recommends requires) ],':custom'=>\&_prefix_custom,},'1.4'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_optional_features_1_4,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_4,'configure_requires'=>\&_keep,':custom'=>\&_keep },'1.3'=>{'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'meta-spec'=>\&_change_meta_spec,'name'=>\&_keep,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'keywords'=>\&_keep,'no_index'=>\&_no_index_directory,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'recommends'=>\&_version_map,'requires'=>\&_version_map,'resources'=>\&_resources_1_3,':custom'=>\&_keep },'1.2'=>{'version'=>\&_keep,'license'=>\&_license_1,'name'=>\&_keep,'generated_by'=>\&_generated_by,'abstract'=>\&_keep_or_unknown,'author'=>\&_author_list,'meta-spec'=>\&_change_meta_spec,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'recommends'=>\&_version_map,'requires'=>\&_version_map,'keywords'=>\&_keep,'no_index'=>\&_no_index_1_2,'optional_features'=>\&_optional_features_as_map,'provides'=>\&_provides,'resources'=>\&_resources_1_2,':custom'=>\&_keep },'1.1'=>{'version'=>\&_keep,'name'=>\&_keep,'meta-spec'=>\&_change_meta_spec,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'recommends'=>\&_version_map,'requires'=>\&_version_map,'license_url'=>\&_url_or_drop,'private'=>\&_keep,':custom'=>\&_keep },'1.0'=>{'name'=>\&_keep,'meta-spec'=>\&_change_meta_spec,'version'=>\&_keep,'build_requires'=>\&_version_map,'conflicts'=>\&_version_map,'distribution_type'=>\&_keep,'dynamic_config'=>\&_keep_or_one,'generated_by'=>\&_generated_by,'license'=>\&_license_1,'recommends'=>\&_version_map,'requires'=>\&_version_map,':custom'=>\&_keep,},);sub new {my ($class,$data)=@_;my$self={'data'=>$data,'spec'=>$data->{'meta-spec'}{'version'}|| "1.0",};return bless$self,$class}sub convert {my ($self,%args)=@_;my$args={%args };my$new_version=$args->{version}|| $HIGHEST;my ($old_version)=$self->{spec};my$converted=_dclone($self->{data});if ($old_version==$new_version){$converted=_convert($converted,$cleanup{$old_version},$old_version);my$cmv=CPAN::Meta::Validator->new($converted);unless ($cmv->is_valid){my$errs=join("\n",$cmv->errors);die "Failed to clean-up $old_version metadata. Errors:\n$errs\n"}return$converted}elsif ($old_version > $new_version){my@vers=sort {$b <=> $a}keys%known_specs;for my$i (0 .. $#vers-1){next if$vers[$i]> $old_version;last if$vers[$i+1]< $new_version;my$spec_string="$vers[$i+1]-from-$vers[$i]";$converted=_convert($converted,$down_convert{$spec_string},$vers[$i+1]);my$cmv=CPAN::Meta::Validator->new($converted);unless ($cmv->is_valid){my$errs=join("\n",$cmv->errors);die "Failed to downconvert metadata to $vers[$i+1]. Errors:\n$errs\n"}}return$converted}else {my@vers=sort {$a <=> $b}keys%known_specs;for my$i (0 .. $#vers-1){next if$vers[$i]< $old_version;last if$vers[$i+1]> $new_version;my$spec_string="$vers[$i+1]-from-$vers[$i]";$converted=_convert($converted,$up_convert{$spec_string},$vers[$i+1]);my$cmv=CPAN::Meta::Validator->new($converted);unless ($cmv->is_valid){my$errs=join("\n",$cmv->errors);die "Failed to upconvert metadata to $vers[$i+1]. Errors:\n$errs\n"}}return$converted}}1;
 CPAN_META_CONVERTER
 
-$fatpacked{"CPAN/Meta/Feature.pm"} = <<'CPAN_META_FEATURE';
+$fatpacked{"CPAN/Meta/Feature.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_FEATURE';
   use 5.006;use strict;use warnings;package CPAN::Meta::Feature;our$VERSION='2.132510';use CPAN::Meta::Prereqs;sub new {my ($class,$identifier,$spec)=@_;my%guts=(identifier=>$identifier,description=>$spec->{description},prereqs=>CPAN::Meta::Prereqs->new($spec->{prereqs}),);bless \%guts=>$class}sub identifier {$_[0]{identifier}}sub description {$_[0]{description}}sub prereqs {$_[0]{prereqs}}1;
 CPAN_META_FEATURE
 
-$fatpacked{"CPAN/Meta/History.pm"} = <<'CPAN_META_HISTORY';
+$fatpacked{"CPAN/Meta/History.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_HISTORY';
   use 5.006;use strict;use warnings;package CPAN::Meta::History;our$VERSION='2.132510';1;
 CPAN_META_HISTORY
 
-$fatpacked{"CPAN/Meta/Prereqs.pm"} = <<'CPAN_META_PREREQS';
+$fatpacked{"CPAN/Meta/Prereqs.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_PREREQS';
   use 5.006;use strict;use warnings;package CPAN::Meta::Prereqs;our$VERSION='2.132510';use Carp qw(confess);use Scalar::Util qw(blessed);use CPAN::Meta::Requirements 2.121;sub __legal_phases {qw(configure build test runtime develop)}sub __legal_types {qw(requires recommends suggests conflicts)}sub new {my ($class,$prereq_spec)=@_;$prereq_spec ||={};my%is_legal_phase=map {;$_=>1}$class->__legal_phases;my%is_legal_type=map {;$_=>1}$class->__legal_types;my%guts;PHASE: for my$phase (keys %$prereq_spec){next PHASE unless$phase =~ /\Ax_/i or $is_legal_phase{$phase};my$phase_spec=$prereq_spec->{$phase };next PHASE unless keys %$phase_spec;TYPE: for my$type (keys %$phase_spec){next TYPE unless$type =~ /\Ax_/i or $is_legal_type{$type};my$spec=$phase_spec->{$type };next TYPE unless keys %$spec;$guts{prereqs}{$phase}{$type}=CPAN::Meta::Requirements->from_string_hash($spec)}}return bless \%guts=>$class}sub requirements_for {my ($self,$phase,$type)=@_;confess "requirements_for called without phase" unless defined$phase;confess "requirements_for called without type" unless defined$type;unless ($phase =~ /\Ax_/i or grep {$phase eq $_}$self->__legal_phases){confess "requested requirements for unknown phase: $phase"}unless ($type =~ /\Ax_/i or grep {$type eq $_}$self->__legal_types){confess "requested requirements for unknown type: $type"}my$req=($self->{prereqs}{$phase}{$type}||=CPAN::Meta::Requirements->new);$req->finalize if$self->is_finalized;return$req}sub with_merged_prereqs {my ($self,$other)=@_;my@other=blessed($other)? $other : @$other;my@prereq_objs=($self,@other);my%new_arg;for my$phase ($self->__legal_phases){for my$type ($self->__legal_types){my$req=CPAN::Meta::Requirements->new;for my$prereq (@prereq_objs){my$this_req=$prereq->requirements_for($phase,$type);next unless$this_req->required_modules;$req->add_requirements($this_req)}next unless$req->required_modules;$new_arg{$phase }{$type }=$req->as_string_hash}}return (ref$self)->new(\%new_arg)}sub as_string_hash {my ($self)=@_;my%hash;for my$phase ($self->__legal_phases){for my$type ($self->__legal_types){my$req=$self->requirements_for($phase,$type);next unless$req->required_modules;$hash{$phase }{$type }=$req->as_string_hash}}return \%hash}sub is_finalized {$_[0]{finalized}}sub finalize {my ($self)=@_;$self->{finalized}=1;for my$phase (keys %{$self->{prereqs}}){$_->finalize for values %{$self->{prereqs}{$phase}}}}sub clone {my ($self)=@_;my$clone=(ref$self)->new($self->as_string_hash)}1;
 CPAN_META_PREREQS
 
-$fatpacked{"CPAN/Meta/Requirements.pm"} = <<'CPAN_META_REQUIREMENTS';
+$fatpacked{"CPAN/Meta/Requirements.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_REQUIREMENTS';
   use strict;use warnings;package CPAN::Meta::Requirements;our$VERSION='2.123';use Carp ();use Scalar::Util ();use version 0.77 ();my@valid_options=qw(bad_version_hook);sub new {my ($class,$options)=@_;$options ||={};Carp::croak "Argument to $class\->new() must be a hash reference" unless ref$options eq 'HASH';my%self=map {;$_=>$options->{$_}}@valid_options;return bless \%self=>$class}sub _version_object {my ($self,$version)=@_;my$vobj;eval {$vobj=(!defined$version)? version->parse(0): (!Scalar::Util::blessed($version))? version->parse($version): $version};if (my$err=$@){my$hook=$self->{bad_version_hook};$vobj=eval {$hook->($version)}if ref$hook eq 'CODE';unless (Scalar::Util::blessed($vobj)&& $vobj->isa("version")){$err =~ s{ at .* line \d+.*$}{};die "Can't convert '$version': $err"}}if ($vobj =~ m{\A\.}){$vobj=version->parse("0$vobj")}if ($vobj->is_qv){$vobj=version->parse($vobj->normal)}return$vobj}BEGIN {for my$type (qw(minimum maximum exclusion exact_version)){my$method="with_$type";my$to_add=$type eq 'exact_version' ? $type : "add_$type";my$code=sub {my ($self,$name,$version)=@_;$version=$self->_version_object($version);$self->__modify_entry_for($name,$method,$version);return$self};no strict 'refs';*$to_add=$code}}sub add_requirements {my ($self,$req)=@_;for my$module ($req->required_modules){my$modifiers=$req->__entry_for($module)->as_modifiers;for my$modifier (@$modifiers){my ($method,@args)=@$modifier;$self->$method($module=>@args)}}return$self}sub accepts_module {my ($self,$module,$version)=@_;$version=$self->_version_object($version);return 1 unless my$range=$self->__entry_for($module);return$range->_accepts($version)}sub clear_requirement {my ($self,$module)=@_;return$self unless$self->__entry_for($module);Carp::confess("can't clear requirements on finalized requirements")if$self->is_finalized;delete$self->{requirements}{$module };return$self}sub requirements_for_module {my ($self,$module)=@_;my$entry=$self->__entry_for($module);return unless$entry;return$entry->as_string}sub required_modules {keys %{$_[0]{requirements}}}sub clone {my ($self)=@_;my$new=(ref$self)->new;return$new->add_requirements($self)}sub __entry_for {$_[0]{requirements}{$_[1]}}sub __modify_entry_for {my ($self,$name,$method,$version)=@_;my$fin=$self->is_finalized;my$old=$self->__entry_for($name);Carp::confess("can't add new requirements to finalized requirements")if$fin and not $old;my$new=($old || 'CPAN::Meta::Requirements::_Range::Range')->$method($version);Carp::confess("can't modify finalized requirements")if$fin and $old->as_string ne $new->as_string;$self->{requirements}{$name }=$new}sub is_simple {my ($self)=@_;for my$module ($self->required_modules){return if$self->__entry_for($module)->as_string =~ /\s/}return 1}sub is_finalized {$_[0]{finalized}}sub finalize {$_[0]{finalized}=1}sub as_string_hash {my ($self)=@_;my%hash=map {;$_=>$self->{requirements}{$_}->as_string}$self->required_modules;return \%hash}my%methods_for_op=('=='=>[qw(exact_version) ],'!='=>[qw(add_exclusion) ],'>='=>[qw(add_minimum) ],'<='=>[qw(add_maximum) ],'>'=>[qw(add_minimum add_exclusion) ],'<'=>[qw(add_maximum add_exclusion) ],);sub add_string_requirement {my ($self,$module,$req)=@_;Carp::confess("No requirement string provided for $module")unless defined$req && length$req;my@parts=split qr{\s*,\s*},$req;for my$part (@parts){my ($op,$ver)=$part =~ m{\A\s*(==|>=|>|<=|<|!=)\s*(.*)\z};if (!defined$op){$self->add_minimum($module=>$part)}else {Carp::confess("illegal requirement string: $req")unless my$methods=$methods_for_op{$op };$self->$_($module=>$ver)for @$methods}}}sub from_string_hash {my ($class,$hash)=@_;my$self=$class->new;for my$module (keys %$hash){my$req=$hash->{$module};unless (defined$req && length$req){$req=0;Carp::carp("Undefined requirement for $module treated as '0'")}$self->add_string_requirement($module,$req)}return$self}{package CPAN::Meta::Requirements::_Range::Exact;sub _new {bless {version=>$_[1]}=>$_[0]}sub _accepts {return $_[0]{version}==$_[1]}sub as_string {return "== $_[0]{version}"}sub as_modifiers {return [[exact_version=>$_[0]{version}]]}sub _clone {(ref $_[0])->_new(version->new($_[0]{version}))}sub with_exact_version {my ($self,$version)=@_;return$self->_clone if$self->_accepts($version);Carp::confess("illegal requirements: unequal exact version specified")}sub with_minimum {my ($self,$minimum)=@_;return$self->_clone if$self->{version}>= $minimum;Carp::confess("illegal requirements: minimum above exact specification")}sub with_maximum {my ($self,$maximum)=@_;return$self->_clone if$self->{version}<= $maximum;Carp::confess("illegal requirements: maximum below exact specification")}sub with_exclusion {my ($self,$exclusion)=@_;return$self->_clone unless$exclusion==$self->{version};Carp::confess("illegal requirements: excluded exact specification")}}{package CPAN::Meta::Requirements::_Range::Range;sub _self {ref($_[0])? $_[0]: (bless {}=>$_[0])}sub _clone {return (bless {}=>$_[0])unless ref $_[0];my ($s)=@_;my%guts=((exists$s->{minimum}? (minimum=>version->new($s->{minimum})): ()),(exists$s->{maximum}? (maximum=>version->new($s->{maximum})): ()),(exists$s->{exclusions}? (exclusions=>[map {version->new($_)}@{$s->{exclusions}}]): ()),);bless \%guts=>ref($s)}sub as_modifiers {my ($self)=@_;my@mods;push@mods,[add_minimum=>$self->{minimum}]if exists$self->{minimum};push@mods,[add_maximum=>$self->{maximum}]if exists$self->{maximum};push@mods,map {;[add_exclusion=>$_ ]}@{$self->{exclusions}|| []};return \@mods}sub as_string {my ($self)=@_;return 0 if!keys %$self;return "$self->{minimum}" if (keys %$self)==1 and exists$self->{minimum};my@exclusions=@{$self->{exclusions}|| []};my@parts;for my$pair ([qw(>= > minimum) ],[qw(<= < maximum) ],){my ($op,$e_op,$k)=@$pair;if (exists$self->{$k}){my@new_exclusions=grep {$_!=$self->{$k }}@exclusions;if (@new_exclusions==@exclusions){push@parts,"$op $self->{ $k }"}else {push@parts,"$e_op $self->{ $k }";@exclusions=@new_exclusions}}}push@parts,map {;"!= $_"}@exclusions;return join q{, },@parts}sub with_exact_version {my ($self,$version)=@_;$self=$self->_clone;Carp::confess("illegal requirements: exact specification outside of range")unless$self->_accepts($version);return CPAN::Meta::Requirements::_Range::Exact->_new($version)}sub _simplify {my ($self)=@_;if (defined$self->{minimum}and defined$self->{maximum}){if ($self->{minimum}==$self->{maximum}){Carp::confess("illegal requirements: excluded all values")if grep {$_==$self->{minimum}}@{$self->{exclusions}|| []};return CPAN::Meta::Requirements::_Range::Exact->_new($self->{minimum})}Carp::confess("illegal requirements: minimum exceeds maximum")if$self->{minimum}> $self->{maximum}}if ($self->{exclusions}){my%seen;@{$self->{exclusions}}=grep {(!defined$self->{minimum}or $_ >= $self->{minimum})and (!defined$self->{maximum}or $_ <= $self->{maximum})and !$seen{$_}++}@{$self->{exclusions}}}return$self}sub with_minimum {my ($self,$minimum)=@_;$self=$self->_clone;if (defined (my$old_min=$self->{minimum})){$self->{minimum}=(sort {$b cmp $a}($minimum,$old_min))[0]}else {$self->{minimum}=$minimum}return$self->_simplify}sub with_maximum {my ($self,$maximum)=@_;$self=$self->_clone;if (defined (my$old_max=$self->{maximum})){$self->{maximum}=(sort {$a cmp $b}($maximum,$old_max))[0]}else {$self->{maximum}=$maximum}return$self->_simplify}sub with_exclusion {my ($self,$exclusion)=@_;$self=$self->_clone;push @{$self->{exclusions}||=[]},$exclusion;return$self->_simplify}sub _accepts {my ($self,$version)=@_;return if defined$self->{minimum}and $version < $self->{minimum};return if defined$self->{maximum}and $version > $self->{maximum};return if defined$self->{exclusions}and grep {$version==$_}@{$self->{exclusions}};return 1}}1;
 CPAN_META_REQUIREMENTS
 
-$fatpacked{"CPAN/Meta/Spec.pm"} = <<'CPAN_META_SPEC';
+$fatpacked{"CPAN/Meta/Spec.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_SPEC';
   use 5.006;use strict;use warnings;package CPAN::Meta::Spec;our$VERSION='2.132510';1;
 CPAN_META_SPEC
 
-$fatpacked{"CPAN/Meta/Validator.pm"} = <<'CPAN_META_VALIDATOR';
+$fatpacked{"CPAN/Meta/Validator.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_VALIDATOR';
   use 5.006;use strict;use warnings;package CPAN::Meta::Validator;our$VERSION='2.132510';my%known_specs=('1.4'=>'http://module-build.sourceforge.net/META-spec-v1.4.html','1.3'=>'http://module-build.sourceforge.net/META-spec-v1.3.html','1.2'=>'http://module-build.sourceforge.net/META-spec-v1.2.html','1.1'=>'http://module-build.sourceforge.net/META-spec-v1.1.html','1.0'=>'http://module-build.sourceforge.net/META-spec-v1.0.html');my%known_urls=map {$known_specs{$_}=>$_}keys%known_specs;my$module_map1={'map'=>{':key'=>{name=>\&module,value=>\&exversion }}};my$module_map2={'map'=>{':key'=>{name=>\&module,value=>\&version }}};my$no_index_2={'map'=>{file=>{list=>{value=>\&string }},directory=>{list=>{value=>\&string }},'package'=>{list=>{value=>\&string }},namespace=>{list=>{value=>\&string }},':key'=>{name=>\&custom_2,value=>\&anything },}};my$no_index_1_3={'map'=>{file=>{list=>{value=>\&string }},directory=>{list=>{value=>\&string }},'package'=>{list=>{value=>\&string }},namespace=>{list=>{value=>\&string }},':key'=>{name=>\&string,value=>\&anything },}};my$no_index_1_2={'map'=>{file=>{list=>{value=>\&string }},dir=>{list=>{value=>\&string }},'package'=>{list=>{value=>\&string }},namespace=>{list=>{value=>\&string }},':key'=>{name=>\&string,value=>\&anything },}};my$no_index_1_1={'map'=>{':key'=>{name=>\&string,list=>{value=>\&string }},}};my$prereq_map={map=>{':key'=>{name=>\&phase,'map'=>{':key'=>{name=>\&relation,%$module_map1,},},}},};my%definitions=('2'=>{'abstract'=>{mandatory=>1,value=>\&string },'author'=>{mandatory=>1,lazylist=>{value=>\&string }},'dynamic_config'=>{mandatory=>1,value=>\&boolean },'generated_by'=>{mandatory=>1,value=>\&string },'license'=>{mandatory=>1,lazylist=>{value=>\&license }},'meta-spec'=>{mandatory=>1,'map'=>{version=>{mandatory=>1,value=>\&version},url=>{value=>\&url },':key'=>{name=>\&custom_2,value=>\&anything },}},'name'=>{mandatory=>1,value=>\&string },'release_status'=>{mandatory=>1,value=>\&release_status },'version'=>{mandatory=>1,value=>\&version },'description'=>{value=>\&string },'keywords'=>{lazylist=>{value=>\&string }},'no_index'=>$no_index_2,'optional_features'=>{'map'=>{':key'=>{name=>\&string,'map'=>{description=>{value=>\&string },prereqs=>$prereq_map,':key'=>{name=>\&custom_2,value=>\&anything },}}}},'prereqs'=>$prereq_map,'provides'=>{'map'=>{':key'=>{name=>\&module,'map'=>{file=>{mandatory=>1,value=>\&file },version=>{value=>\&version },':key'=>{name=>\&custom_2,value=>\&anything },}}}},'resources'=>{'map'=>{license=>{lazylist=>{value=>\&url }},homepage=>{value=>\&url },bugtracker=>{'map'=>{web=>{value=>\&url },mailto=>{value=>\&string},':key'=>{name=>\&custom_2,value=>\&anything },}},repository=>{'map'=>{web=>{value=>\&url },url=>{value=>\&url },type=>{value=>\&string },':key'=>{name=>\&custom_2,value=>\&anything },}},':key'=>{value=>\&string,name=>\&custom_2 },}},':key'=>{name=>\&custom_2,value=>\&anything },},'1.4'=>{'meta-spec'=>{mandatory=>1,'map'=>{version=>{mandatory=>1,value=>\&version},url=>{mandatory=>1,value=>\&urlspec },':key'=>{name=>\&string,value=>\&anything },},},'name'=>{mandatory=>1,value=>\&string },'version'=>{mandatory=>1,value=>\&version },'abstract'=>{mandatory=>1,value=>\&string },'author'=>{mandatory=>1,list=>{value=>\&string }},'license'=>{mandatory=>1,value=>\&license },'generated_by'=>{mandatory=>1,value=>\&string },'distribution_type'=>{value=>\&string },'dynamic_config'=>{value=>\&boolean },'requires'=>$module_map1,'recommends'=>$module_map1,'build_requires'=>$module_map1,'configure_requires'=>$module_map1,'conflicts'=>$module_map2,'optional_features'=>{'map'=>{':key'=>{name=>\&string,'map'=>{description=>{value=>\&string },requires=>$module_map1,recommends=>$module_map1,build_requires=>$module_map1,conflicts=>$module_map2,':key'=>{name=>\&string,value=>\&anything },}}}},'provides'=>{'map'=>{':key'=>{name=>\&module,'map'=>{file=>{mandatory=>1,value=>\&file },version=>{value=>\&version },':key'=>{name=>\&string,value=>\&anything },}}}},'no_index'=>$no_index_1_3,'private'=>$no_index_1_3,'keywords'=>{list=>{value=>\&string }},'resources'=>{'map'=>{license=>{value=>\&url },homepage=>{value=>\&url },bugtracker=>{value=>\&url },repository=>{value=>\&url },':key'=>{value=>\&string,name=>\&custom_1 },}},':key'=>{name=>\&string,value=>\&anything },},'1.3'=>{'meta-spec'=>{mandatory=>1,'map'=>{version=>{mandatory=>1,value=>\&version},url=>{mandatory=>1,value=>\&urlspec },':key'=>{name=>\&string,value=>\&anything },},},'name'=>{mandatory=>1,value=>\&string },'version'=>{mandatory=>1,value=>\&version },'abstract'=>{mandatory=>1,value=>\&string },'author'=>{mandatory=>1,list=>{value=>\&string }},'license'=>{mandatory=>1,value=>\&license },'generated_by'=>{mandatory=>1,value=>\&string },'distribution_type'=>{value=>\&string },'dynamic_config'=>{value=>\&boolean },'requires'=>$module_map1,'recommends'=>$module_map1,'build_requires'=>$module_map1,'conflicts'=>$module_map2,'optional_features'=>{'map'=>{':key'=>{name=>\&string,'map'=>{description=>{value=>\&string },requires=>$module_map1,recommends=>$module_map1,build_requires=>$module_map1,conflicts=>$module_map2,':key'=>{name=>\&string,value=>\&anything },}}}},'provides'=>{'map'=>{':key'=>{name=>\&module,'map'=>{file=>{mandatory=>1,value=>\&file },version=>{value=>\&version },':key'=>{name=>\&string,value=>\&anything },}}}},'no_index'=>$no_index_1_3,'private'=>$no_index_1_3,'keywords'=>{list=>{value=>\&string }},'resources'=>{'map'=>{license=>{value=>\&url },homepage=>{value=>\&url },bugtracker=>{value=>\&url },repository=>{value=>\&url },':key'=>{value=>\&string,name=>\&custom_1 },}},':key'=>{name=>\&string,value=>\&anything },},'1.2'=>{'meta-spec'=>{mandatory=>1,'map'=>{version=>{mandatory=>1,value=>\&version},url=>{mandatory=>1,value=>\&urlspec },':key'=>{name=>\&string,value=>\&anything },},},'name'=>{mandatory=>1,value=>\&string },'version'=>{mandatory=>1,value=>\&version },'license'=>{mandatory=>1,value=>\&license },'generated_by'=>{mandatory=>1,value=>\&string },'author'=>{mandatory=>1,list=>{value=>\&string }},'abstract'=>{mandatory=>1,value=>\&string },'distribution_type'=>{value=>\&string },'dynamic_config'=>{value=>\&boolean },'keywords'=>{list=>{value=>\&string }},'private'=>$no_index_1_2,'$no_index'=>$no_index_1_2,'requires'=>$module_map1,'recommends'=>$module_map1,'build_requires'=>$module_map1,'conflicts'=>$module_map2,'optional_features'=>{'map'=>{':key'=>{name=>\&string,'map'=>{description=>{value=>\&string },requires=>$module_map1,recommends=>$module_map1,build_requires=>$module_map1,conflicts=>$module_map2,':key'=>{name=>\&string,value=>\&anything },}}}},'provides'=>{'map'=>{':key'=>{name=>\&module,'map'=>{file=>{mandatory=>1,value=>\&file },version=>{value=>\&version },':key'=>{name=>\&string,value=>\&anything },}}}},'resources'=>{'map'=>{license=>{value=>\&url },homepage=>{value=>\&url },bugtracker=>{value=>\&url },repository=>{value=>\&url },':key'=>{value=>\&string,name=>\&custom_1 },}},':key'=>{name=>\&string,value=>\&anything },},'1.1'=>{'name'=>{value=>\&string },'version'=>{mandatory=>1,value=>\&version },'license'=>{value=>\&license },'generated_by'=>{value=>\&string },'license_uri'=>{value=>\&url },'distribution_type'=>{value=>\&string },'dynamic_config'=>{value=>\&boolean },'private'=>$no_index_1_1,'requires'=>$module_map1,'recommends'=>$module_map1,'build_requires'=>$module_map1,'conflicts'=>$module_map2,':key'=>{name=>\&string,value=>\&anything },},'1.0'=>{'name'=>{value=>\&string },'version'=>{mandatory=>1,value=>\&version },'license'=>{value=>\&license },'generated_by'=>{value=>\&string },'license_uri'=>{value=>\&url },'distribution_type'=>{value=>\&string },'dynamic_config'=>{value=>\&boolean },'requires'=>$module_map1,'recommends'=>$module_map1,'build_requires'=>$module_map1,'conflicts'=>$module_map2,':key'=>{name=>\&string,value=>\&anything },},);sub new {my ($class,$data)=@_;my$self={'data'=>$data,'spec'=>$data->{'meta-spec'}{'version'}|| "1.0",'errors'=>undef,};return bless$self,$class}sub is_valid {my$self=shift;my$data=$self->{data};my$spec_version=$self->{spec};$self->check_map($definitions{$spec_version},$data);return!$self->errors}sub errors {my$self=shift;return ()unless(defined$self->{errors});return @{$self->{errors}}}my$spec_error="Missing validation action in specification. " ."Must be one of 'map', 'list', 'lazylist', or 'value'";sub check_map {my ($self,$spec,$data)=@_;if(ref($spec)ne 'HASH'){$self->_error("Unknown META specification, cannot validate.");return}if(ref($data)ne 'HASH'){$self->_error("Expected a map structure from string or file.");return}for my$key (keys %$spec){next unless($spec->{$key}->{mandatory});next if(defined$data->{$key});push @{$self->{stack}},$key;$self->_error("Missing mandatory field, '$key'");pop @{$self->{stack}}}for my$key (keys %$data){push @{$self->{stack}},$key;if($spec->{$key}){if($spec->{$key}{value}){$spec->{$key}{value}->($self,$key,$data->{$key})}elsif($spec->{$key}{'map'}){$self->check_map($spec->{$key}{'map'},$data->{$key})}elsif($spec->{$key}{'list'}){$self->check_list($spec->{$key}{'list'},$data->{$key})}elsif($spec->{$key}{'lazylist'}){$self->check_lazylist($spec->{$key}{'lazylist'},$data->{$key})}else {$self->_error("$spec_error for '$key'")}}elsif ($spec->{':key'}){$spec->{':key'}{name}->($self,$key,$key);if($spec->{':key'}{value}){$spec->{':key'}{value}->($self,$key,$data->{$key})}elsif($spec->{':key'}{'map'}){$self->check_map($spec->{':key'}{'map'},$data->{$key})}elsif($spec->{':key'}{'list'}){$self->check_list($spec->{':key'}{'list'},$data->{$key})}elsif($spec->{':key'}{'lazylist'}){$self->check_lazylist($spec->{':key'}{'lazylist'},$data->{$key})}else {$self->_error("$spec_error for ':key'")}}else {$self->_error("Unknown key, '$key', found in map structure")}pop @{$self->{stack}}}}sub check_lazylist {my ($self,$spec,$data)=@_;if (defined$data &&!ref($data)){$data=[$data ]}$self->check_list($spec,$data)}sub check_list {my ($self,$spec,$data)=@_;if(ref($data)ne 'ARRAY'){$self->_error("Expected a list structure");return}if(defined$spec->{mandatory}){if(!defined$data->[0]){$self->_error("Missing entries from mandatory list")}}for my$value (@$data){push @{$self->{stack}},$value || "<undef>";if(defined$spec->{value}){$spec->{value}->($self,'list',$value)}elsif(defined$spec->{'map'}){$self->check_map($spec->{'map'},$value)}elsif(defined$spec->{'list'}){$self->check_list($spec->{'list'},$value)}elsif(defined$spec->{'lazylist'}){$self->check_lazylist($spec->{'lazylist'},$value)}elsif ($spec->{':key'}){$self->check_map($spec,$value)}else {$self->_error("$spec_error associated with '$self->{stack}[-2]'")}pop @{$self->{stack}}}}sub header {my ($self,$key,$value)=@_;if(defined$value){return 1 if($value && $value =~ /^--- #YAML:1.0/)}$self->_error("file does not have a valid YAML header.");return 0}sub release_status {my ($self,$key,$value)=@_;if(defined$value){my$version=$self->{data}{version}|| '';if ($version =~ /_/){return 1 if ($value =~ /\A(?:testing|unstable)\z/);$self->_error("'$value' for '$key' is invalid for version '$version'")}else {return 1 if ($value =~ /\A(?:stable|testing|unstable)\z/);$self->_error("'$value' for '$key' is invalid")}}else {$self->_error("'$key' is not defined")}return 0}sub _uri_split {return $_[0]=~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?,}sub url {my ($self,$key,$value)=@_;if(defined$value){my ($scheme,$auth,$path,$query,$frag)=_uri_split($value);unless (defined$scheme && length$scheme){$self->_error("'$value' for '$key' does not have a URL scheme");return 0}unless (defined$auth && length$auth){$self->_error("'$value' for '$key' does not have a URL authority");return 0}return 1}$value ||='';$self->_error("'$value' for '$key' is not a valid URL.");return 0}sub urlspec {my ($self,$key,$value)=@_;if(defined$value){return 1 if($value && $known_specs{$self->{spec}}eq $value);if($value && $known_urls{$value}){$self->_error('META specification URL does not match version');return 0}}$self->_error('Unknown META specification');return 0}sub anything {return 1}sub string {my ($self,$key,$value)=@_;if(defined$value){return 1 if($value || $value =~ /^0$/)}$self->_error("value is an undefined string");return 0}sub string_or_undef {my ($self,$key,$value)=@_;return 1 unless(defined$value);return 1 if($value || $value =~ /^0$/);$self->_error("No string defined for '$key'");return 0}sub file {my ($self,$key,$value)=@_;return 1 if(defined$value);$self->_error("No file defined for '$key'");return 0}sub exversion {my ($self,$key,$value)=@_;if(defined$value && ($value || $value =~ /0/)){my$pass=1;for(split(",",$value)){$self->version($key,$_)or ($pass=0)}return$pass}$value='<undef>' unless(defined$value);$self->_error("'$value' for '$key' is not a valid version.");return 0}sub version {my ($self,$key,$value)=@_;if(defined$value){return 0 unless($value || $value =~ /0/);return 1 if($value =~ /^\s*((<|<=|>=|>|!=|==)\s*)?v?\d+((\.\d+((_|\.)\d+)?)?)/)}else {$value='<undef>'}$self->_error("'$value' for '$key' is not a valid version.");return 0}sub boolean {my ($self,$key,$value)=@_;if(defined$value){return 1 if($value =~ /^(0|1|true|false)$/)}else {$value='<undef>'}$self->_error("'$value' for '$key' is not a boolean value.");return 0}my%v1_licenses=('perl'=>'http://dev.perl.org/licenses/','gpl'=>'http://www.opensource.org/licenses/gpl-license.php','apache'=>'http://apache.org/licenses/LICENSE-2.0','artistic'=>'http://opensource.org/licenses/artistic-license.php','artistic_2'=>'http://opensource.org/licenses/artistic-license-2.0.php','lgpl'=>'http://www.opensource.org/licenses/lgpl-license.php','bsd'=>'http://www.opensource.org/licenses/bsd-license.php','gpl'=>'http://www.opensource.org/licenses/gpl-license.php','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,);my%v2_licenses=map {$_=>1}qw(agpl_3 apache_1_1 apache_2_0 artistic_1 artistic_2 bsd freebsd gfdl_1_2 gfdl_1_3 gpl_1 gpl_2 gpl_3 lgpl_2_1 lgpl_3_0 mit mozilla_1_0 mozilla_1_1 openssl perl_5 qpl_1_0 ssleay sun zlib open_source restricted unrestricted unknown);sub license {my ($self,$key,$value)=@_;my$licenses=$self->{spec}< 2 ? \%v1_licenses : \%v2_licenses;if(defined$value){return 1 if($value && exists$licenses->{$value})}else {$value='<undef>'}$self->_error("License '$value' is invalid");return 0}sub custom_1 {my ($self,$key)=@_;if(defined$key){return 1 if($key && $key =~ /^[_a-z]+$/i && $key =~ /[A-Z]/)}else {$key='<undef>'}$self->_error("Custom resource '$key' must be in CamelCase.");return 0}sub custom_2 {my ($self,$key)=@_;if(defined$key){return 1 if($key && $key =~ /^x_/i)}else {$key='<undef>'}$self->_error("Custom key '$key' must begin with 'x_' or 'X_'.");return 0}sub identifier {my ($self,$key)=@_;if(defined$key){return 1 if($key && $key =~ /^([a-z][_a-z]+)$/i)}else {$key='<undef>'}$self->_error("Key '$key' is not a legal identifier.");return 0}sub module {my ($self,$key)=@_;if(defined$key){return 1 if($key && $key =~ /^[A-Za-z0-9_]+(::[A-Za-z0-9_]+)*$/)}else {$key='<undef>'}$self->_error("Key '$key' is not a legal module name.");return 0}my@valid_phases=qw/configure build test runtime develop/;sub phase {my ($self,$key)=@_;if(defined$key){return 1 if(length$key && grep {$key eq $_}@valid_phases);return 1 if$key =~ /x_/i}else {$key='<undef>'}$self->_error("Key '$key' is not a legal phase.");return 0}my@valid_relations=qw/requires recommends suggests conflicts/;sub relation {my ($self,$key)=@_;if(defined$key){return 1 if(length$key && grep {$key eq $_}@valid_relations);return 1 if$key =~ /x_/i}else {$key='<undef>'}$self->_error("Key '$key' is not a legal prereq relationship.");return 0}sub _error {my$self=shift;my$mess=shift;$mess .= ' ('.join(' -> ',@{$self->{stack}}).')' if($self->{stack});$mess .= " [Validation: $self->{spec}]";push @{$self->{errors}},$mess}1;
 CPAN_META_VALIDATOR
 
-$fatpacked{"CPAN/Meta/YAML.pm"} = <<'CPAN_META_YAML';
+$fatpacked{"CPAN/Meta/YAML.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_YAML';
   package CPAN::Meta::YAML;{$CPAN::Meta::YAML::VERSION='0.008'}use strict;sub HAVE_UTF8 () {$] >= 5.007003}BEGIN {if (HAVE_UTF8){eval "require utf8;";die "Failed to load UTF-8 support" if $@}require 5.004;require Exporter;require Carp;@CPAN::Meta::YAML::ISA=qw{Exporter};@CPAN::Meta::YAML::EXPORT=qw{Load Dump};@CPAN::Meta::YAML::EXPORT_OK=qw{LoadFile DumpFile freeze thaw};$CPAN::Meta::YAML::errstr=''}my@UNPRINTABLE=qw(z x01 x02 x03 x04 x05 x06 a x08 t n v f r x0e x0f x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x1a e x1c x1d x1e x1f);my%UNESCAPES=(z=>"\x00",a=>"\x07",t=>"\x09",n=>"\x0a",v=>"\x0b",f=>"\x0c",r=>"\x0d",e=>"\x1b",'\\'=>'\\',);my%QUOTE=map {$_=>1}qw{null Null NULL y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF};sub new {my$class=shift;bless [@_ ],$class}sub read {my$class=ref $_[0]? ref shift : shift;my$file=shift or return$class->_error('You did not specify a file name');return$class->_error("File '$file' does not exist")unless -e $file;return$class->_error("'$file' is a directory, not a file")unless -f _;return$class->_error("Insufficient permissions to read '$file'")unless -r _;local $/=undef;local*CFG;unless (open(CFG,$file)){return$class->_error("Failed to open file '$file': $!")}my$contents=<CFG>;unless (close(CFG)){return$class->_error("Failed to close file '$file': $!")}$class->read_string($contents)}sub read_string {my$class=ref $_[0]? ref shift : shift;my$self=bless [],$class;my$string=$_[0];eval {unless (defined$string){die \"Did not provide a string to load"}if ($string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/){die \"Stream has a non UTF-8 BOM"}else {$string =~ s/^\357\273\277//}utf8::decode($string)if HAVE_UTF8;return$self unless length$string;unless ($string =~ /[\012\015]+\z/){die \"Stream does not end with newline character"}my@lines=grep {!/^\s*(?:\#.*)?\z/}split /(?:\015{1,2}\012|\015|\012)/,$string;@lines and $lines[0]=~ /^\%YAML[: ][\d\.]+.*\z/ and shift@lines;while (@lines){if ($lines[0]=~ /^---\s*(?:(.+)\s*)?\z/){shift@lines;if (defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/){push @$self,$self->_read_scalar("$1",[undef ],\@lines);next}}if (!@lines or $lines[0]=~ /^(?:---|\.\.\.)/){push @$self,undef;while (@lines and $lines[0]!~ /^---/){shift@lines}}elsif ($lines[0]=~ /^\s*\-/){my$document=[];push @$self,$document;$self->_read_array($document,[0 ],\@lines)}elsif ($lines[0]=~ /^(\s*)\S/){my$document={};push @$self,$document;$self->_read_hash($document,[length($1)],\@lines)}else {die \"CPAN::Meta::YAML failed to classify the line '$lines[0]'"}}};if (ref $@ eq 'SCALAR'){return$self->_error(${$@})}elsif ($@){require Carp;Carp::croak($@)}return$self}sub _read_scalar {my ($self,$string,$indent,$lines)=@_;$string =~ s/\s*\z//;return undef if$string eq '~';if ($string =~ /^\'(.*?)\'(?:\s+\#.*)?\z/){return '' unless defined $1;$string=$1;$string =~ s/\'\'/\'/g;return$string}if ($string =~ /^\"([^\\"]*(?:\\.[^\\"]*)*)\"(?:\s+\#.*)?\z/){$string=$1;$string =~ s/\\"/"/g;$string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex;return$string}if ($string =~ /^[\'\"!&]/){die \"CPAN::Meta::YAML does not support a feature in line '$string'"}return {}if$string =~ /^{}(?:\s+\#.*)?\z/;return []if$string =~ /^\[\](?:\s+\#.*)?\z/;if ($string !~ /^[>|]/){if ($string =~ /^(?:-(?:\s|$)|[\@\%\`])/ or $string =~ /:(?:\s|$)/){die \"CPAN::Meta::YAML found illegal characters in plain scalar: '$string'"}$string =~ s/\s+#.*\z//;return$string}die \"CPAN::Meta::YAML failed to find multi-line scalar content" unless @$lines;$lines->[0]=~ /^(\s*)/;$indent->[-1]=length("$1");if (defined$indent->[-2]and $indent->[-1]<= $indent->[-2]){die \"CPAN::Meta::YAML found bad indenting in line '$lines->[0]'"}my@multiline=();while (@$lines){$lines->[0]=~ /^(\s*)/;last unless length($1)>= $indent->[-1];push@multiline,substr(shift(@$lines),length($1))}my$j=(substr($string,0,1)eq '>')? ' ' : "\n";my$t=(substr($string,1,1)eq '-')? '' : "\n";return join($j,@multiline).$t}sub _read_array {my ($self,$array,$indent,$lines)=@_;while (@$lines){if ($lines->[0]=~ /^(?:---|\.\.\.)/){while (@$lines and $lines->[0]!~ /^---/){shift @$lines}return 1}$lines->[0]=~ /^(\s*)/;if (length($1)< $indent->[-1]){return 1}elsif (length($1)> $indent->[-1]){die \"CPAN::Meta::YAML found bad indenting in line '$lines->[0]'"}if ($lines->[0]=~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/){my$indent2=length("$1");$lines->[0]=~ s/-/ /;push @$array,{};$self->_read_hash($array->[-1],[@$indent,$indent2 ],$lines)}elsif ($lines->[0]=~ /^\s*\-(\s*)(.+?)\s*\z/){shift @$lines;push @$array,$self->_read_scalar("$2",[@$indent,undef ],$lines)}elsif ($lines->[0]=~ /^\s*\-\s*\z/){shift @$lines;unless (@$lines){push @$array,undef;return 1}if ($lines->[0]=~ /^(\s*)\-/){my$indent2=length("$1");if ($indent->[-1]==$indent2){push @$array,undef}else {push @$array,[];$self->_read_array($array->[-1],[@$indent,$indent2 ],$lines)}}elsif ($lines->[0]=~ /^(\s*)\S/){push @$array,{};$self->_read_hash($array->[-1],[@$indent,length("$1")],$lines)}else {die \"CPAN::Meta::YAML failed to classify line '$lines->[0]'"}}elsif (defined$indent->[-2]and $indent->[-1]==$indent->[-2]){return 1}else {die \"CPAN::Meta::YAML failed to classify line '$lines->[0]'"}}return 1}sub _read_hash {my ($self,$hash,$indent,$lines)=@_;while (@$lines){if ($lines->[0]=~ /^(?:---|\.\.\.)/){while (@$lines and $lines->[0]!~ /^---/){shift @$lines}return 1}$lines->[0]=~ /^(\s*)/;if (length($1)< $indent->[-1]){return 1}elsif (length($1)> $indent->[-1]){die \"CPAN::Meta::YAML found bad indenting in line '$lines->[0]'"}unless ($lines->[0]=~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+(?:\#.*)?|$)//){if ($lines->[0]=~ /^\s*[?\'\"]/){die \"CPAN::Meta::YAML does not support a feature in line '$lines->[0]'"}die \"CPAN::Meta::YAML failed to classify line '$lines->[0]'"}my$key=$1;if (length$lines->[0]){$hash->{$key}=$self->_read_scalar(shift(@$lines),[@$indent,undef ],$lines)}else {shift @$lines;unless (@$lines){$hash->{$key}=undef;return 1}if ($lines->[0]=~ /^(\s*)-/){$hash->{$key}=[];$self->_read_array($hash->{$key},[@$indent,length($1)],$lines)}elsif ($lines->[0]=~ /^(\s*)./){my$indent2=length("$1");if ($indent->[-1]>= $indent2){$hash->{$key}=undef}else {$hash->{$key}={};$self->_read_hash($hash->{$key},[@$indent,length($1)],$lines)}}}}return 1}sub write {my$self=shift;my$file=shift or return$self->_error('No file name provided');open(CFG,'>' .$file)or return$self->_error("Failed to open file '$file' for writing: $!");print CFG$self->write_string;close CFG;return 1}sub write_string {my$self=shift;return '' unless @$self;my$indent=0;my@lines=();for my$cursor (@$self){push@lines,'---';if (!defined$cursor){}elsif (!ref$cursor){$lines[-1].= ' ' .$self->_write_scalar($cursor,$indent)}elsif (ref$cursor eq 'ARRAY'){unless (@$cursor){$lines[-1].= ' []';next}push@lines,$self->_write_array($cursor,$indent,{})}elsif (ref$cursor eq 'HASH'){unless (%$cursor){$lines[-1].= ' {}';next}push@lines,$self->_write_hash($cursor,$indent,{})}else {Carp::croak("Cannot serialize " .ref($cursor))}}join '',map {"$_\n"}@lines}sub _write_scalar {my$string=$_[1];return '~' unless defined$string;return "''" unless length$string;if ($string =~ /[\x00-\x08\x0b-\x0d\x0e-\x1f\"\'\n]/){$string =~ s/\\/\\\\/g;$string =~ s/"/\\"/g;$string =~ s/\n/\\n/g;$string =~ s/([\x00-\x1f])/\\$UNPRINTABLE[ord($1)]/g;return qq|"$string"|}if ($string =~ /(?:^\W|\s|:\z)/ or $QUOTE{$string}){return "'$string'"}return$string}sub _write_array {my ($self,$array,$indent,$seen)=@_;if ($seen->{refaddr($array)}++){die "CPAN::Meta::YAML does not support circular references"}my@lines=();for my$el (@$array){my$line=('  ' x $indent).'-';my$type=ref$el;if (!$type){$line .= ' ' .$self->_write_scalar($el,$indent + 1);push@lines,$line}elsif ($type eq 'ARRAY'){if (@$el){push@lines,$line;push@lines,$self->_write_array($el,$indent + 1,$seen)}else {$line .= ' []';push@lines,$line}}elsif ($type eq 'HASH'){if (keys %$el){push@lines,$line;push@lines,$self->_write_hash($el,$indent + 1,$seen)}else {$line .= ' {}';push@lines,$line}}else {die "CPAN::Meta::YAML does not support $type references"}}@lines}sub _write_hash {my ($self,$hash,$indent,$seen)=@_;if ($seen->{refaddr($hash)}++){die "CPAN::Meta::YAML does not support circular references"}my@lines=();for my$name (sort keys %$hash){my$el=$hash->{$name};my$line=('  ' x $indent)."$name:";my$type=ref$el;if (!$type){$line .= ' ' .$self->_write_scalar($el,$indent + 1);push@lines,$line}elsif ($type eq 'ARRAY'){if (@$el){push@lines,$line;push@lines,$self->_write_array($el,$indent + 1,$seen)}else {$line .= ' []';push@lines,$line}}elsif ($type eq 'HASH'){if (keys %$el){push@lines,$line;push@lines,$self->_write_hash($el,$indent + 1,$seen)}else {$line .= ' {}';push@lines,$line}}else {die "CPAN::Meta::YAML does not support $type references"}}@lines}sub _error {$CPAN::Meta::YAML::errstr=$_[1];undef}sub errstr {$CPAN::Meta::YAML::errstr}sub Dump {CPAN::Meta::YAML->new(@_)->write_string}sub Load {my$self=CPAN::Meta::YAML->read_string(@_);unless ($self){Carp::croak("Failed to load YAML document from string")}if (wantarray){return @$self}else {return$self->[-1]}}BEGIN {*freeze=*Dump;*thaw=*Load}sub DumpFile {my$file=shift;CPAN::Meta::YAML->new(@_)->write($file)}sub LoadFile {my$self=CPAN::Meta::YAML->read($_[0]);unless ($self){Carp::croak("Failed to load YAML document from '" .($_[0]|| '')."'")}if (wantarray){return @$self}else {return$self->[-1]}}BEGIN {local $@;eval {require Scalar::Util};my$v=eval("$Scalar::Util::VERSION")|| 0;if ($@ or $v < 1.18){eval <<'END_PERL'}else {*refaddr=*Scalar::Util::refaddr}}1;
   # Scalar::Util failed to load or too old
   sub refaddr {
@@ -230,20 +230,20 @@ $fatpacked{"CPAN/Meta/YAML.pm"} = <<'CPAN_META_YAML';
   END_PERL
 CPAN_META_YAML
 
-$fatpacked{"Exporter.pm"} = <<'EXPORTER';
+$fatpacked{"Exporter.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER';
   package Exporter;require 5.006;our$Debug=0;our$ExportLevel=0;our$Verbose ||=0;our$VERSION='5.68';our (%Cache);sub as_heavy {require Exporter::Heavy;my$c=(caller(1))[3];$c =~ s/.*:://;\&{"Exporter::Heavy::heavy_$c"}}sub export {goto &{as_heavy()}}sub import {my$pkg=shift;my$callpkg=caller($ExportLevel);if ($pkg eq "Exporter" and @_ and $_[0]eq "import"){*{$callpkg."::import"}=\&import;return}my$exports=\@{"$pkg\::EXPORT"};my$fail=${$pkg .'::'}{EXPORT_FAIL}&& \@{"$pkg\::EXPORT_FAIL"};return export$pkg,$callpkg,@_ if$Verbose or $Debug or $fail && @$fail > 1;my$export_cache=($Cache{$pkg}||={});my$args=@_ or @_=@$exports;if ($args and not %$export_cache){s/^&//,$export_cache->{$_}=1 foreach (@$exports,@{"$pkg\::EXPORT_OK"})}my$heavy;if ($args or $fail){($heavy=(/\W/ or $args and not exists$export_cache->{$_}or $fail and @$fail and $_ eq $fail->[0]))and last foreach (@_)}else {($heavy=/\W/)and last foreach (@_)}return export$pkg,$callpkg,($args ? @_ : ())if$heavy;local$SIG{__WARN__}=sub {require Carp;&Carp::carp}if not $SIG{__WARN__};*{"$callpkg\::$_"}=\&{"$pkg\::$_"}foreach @_}sub export_fail {my$self=shift;@_}sub export_to_level {goto &{as_heavy()}}sub export_tags {goto &{as_heavy()}}sub export_ok_tags {goto &{as_heavy()}}sub require_version {goto &{as_heavy()}}1;
 EXPORTER
 
-$fatpacked{"Exporter/Heavy.pm"} = <<'EXPORTER_HEAVY';
+$fatpacked{"Exporter/Heavy.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_HEAVY';
   package Exporter::Heavy;use strict;no strict 'refs';require Exporter;our$VERSION=$Exporter::VERSION;sub _rebuild_cache {my ($pkg,$exports,$cache)=@_;s/^&// foreach @$exports;@{$cache}{@$exports}=(1)x @$exports;my$ok=\@{"${pkg}::EXPORT_OK"};if (@$ok){s/^&// foreach @$ok;@{$cache}{@$ok}=(1)x @$ok}}sub heavy_export {local$SIG{__WARN__}=sub {my$text=shift;if ($text =~ s/ at \S*Exporter\S*.pm line \d+.*\n//){require Carp;local$Carp::CarpLevel=1;Carp::carp($text)}else {warn$text}};local$SIG{__DIE__}=sub {require Carp;local$Carp::CarpLevel=1;Carp::croak("$_[0]Illegal null symbol in \@${1}::EXPORT")if $_[0]=~ /^Unable to create sub named "(.*?)::"/};my($pkg,$callpkg,@imports)=@_;my($type,$sym,$cache_is_current,$oops);my($exports,$export_cache)=(\@{"${pkg}::EXPORT"},$Exporter::Cache{$pkg}||={});if (@imports){if (!%$export_cache){_rebuild_cache ($pkg,$exports,$export_cache);$cache_is_current=1}if (grep m{^[/!:]},@imports){my$tagsref=\%{"${pkg}::EXPORT_TAGS"};my$tagdata;my%imports;my($remove,$spec,@names,@allexports);unshift@imports,':DEFAULT' if$imports[0]=~ m/^!/;for$spec (@imports){$remove=$spec =~ s/^!//;if ($spec =~ s/^://){if ($spec eq 'DEFAULT'){@names=@$exports}elsif ($tagdata=$tagsref->{$spec}){@names=@$tagdata}else {warn qq["$spec" is not defined in %${pkg}::EXPORT_TAGS];++$oops;next}}elsif ($spec =~ m:^/(.*)/$:){my$patn=$1;@allexports=keys %$export_cache unless@allexports;@names=grep(/$patn/,@allexports)}else {@names=($spec)}warn "Import ".($remove ? "del":"add").": @names " if$Exporter::Verbose;if ($remove){for$sym (@names){delete$imports{$sym}}}else {@imports{@names}=(1)x @names}}@imports=keys%imports}my@carp;for$sym (@imports){if (!$export_cache->{$sym}){if ($sym =~ m/^\d/){$pkg->VERSION($sym);if (@imports==1){@imports=@$exports;last}if (@imports==2 and!$imports[1]){@imports=();last}}elsif ($sym !~ s/^&// ||!$export_cache->{$sym}){unless ($cache_is_current){%$export_cache=();_rebuild_cache ($pkg,$exports,$export_cache);$cache_is_current=1}if (!$export_cache->{$sym}){push@carp,qq["$sym" is not exported by the $pkg module\n];$oops++}}}}if ($oops){require Carp;Carp::croak("@{carp}Can't continue after import errors")}}else {@imports=@$exports}my($fail,$fail_cache)=(\@{"${pkg}::EXPORT_FAIL"},$Exporter::FailCache{$pkg}||={});if (@$fail){if (!%$fail_cache){my@expanded=map {/^\w/ ? ($_,'&'.$_): $_}@$fail;warn "${pkg}::EXPORT_FAIL cached: @expanded" if$Exporter::Verbose;@{$fail_cache}{@expanded}=(1)x @expanded}my@failed;for$sym (@imports){push(@failed,$sym)if$fail_cache->{$sym}}if (@failed){@failed=$pkg->export_fail(@failed);for$sym (@failed){require Carp;Carp::carp(qq["$sym" is not implemented by the $pkg module ],"on this architecture")}if (@failed){require Carp;Carp::croak("Can't continue after import errors")}}}warn "Importing into $callpkg from $pkg: ",join(", ",sort@imports)if$Exporter::Verbose;for$sym (@imports){(*{"${callpkg}::$sym"}=\&{"${pkg}::$sym"},next)unless$sym =~ s/^(\W)//;$type=$1;no warnings 'once';*{"${callpkg}::$sym"}=$type eq '&' ? \&{"${pkg}::$sym"}: $type eq '$' ? \${"${pkg}::$sym"}: $type eq '@' ? \@{"${pkg}::$sym"}: $type eq '%' ? \%{"${pkg}::$sym"}: $type eq '*' ? *{"${pkg}::$sym"}: do {require Carp;Carp::croak("Can't export symbol: $type$sym")}}}sub heavy_export_to_level {my$pkg=shift;my$level=shift;(undef)=shift;my$callpkg=caller($level);$pkg->export($callpkg,@_)}sub _push_tags {my($pkg,$var,$syms)=@_;my@nontag=();my$export_tags=\%{"${pkg}::EXPORT_TAGS"};push(@{"${pkg}::$var"},map {$export_tags->{$_}? @{$export_tags->{$_}}: scalar(push(@nontag,$_),$_)}(@$syms)? @$syms : keys %$export_tags);if (@nontag and $^W){require Carp;Carp::carp(join(", ",@nontag)." are not tags of $pkg")}}sub heavy_require_version {my($self,$wanted)=@_;my$pkg=ref$self || $self;return ${pkg}->VERSION($wanted)}sub heavy_export_tags {_push_tags((caller)[0],"EXPORT",\@_)}sub heavy_export_ok_tags {_push_tags((caller)[0],"EXPORT_OK",\@_)}1;
 EXPORTER_HEAVY
 
-$fatpacked{"File/pushd.pm"} = <<'FILE_PUSHD';
+$fatpacked{"File/pushd.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'FILE_PUSHD';
   use strict;use warnings;package File::pushd;our$VERSION='1.005';our@EXPORT=qw(pushd tempd);our@ISA=qw(Exporter);use Exporter;use Carp;use Cwd qw(getcwd abs_path);use File::Path qw(rmtree);use File::Temp qw();use File::Spec;use overload q{""}=>sub {File::Spec->canonpath($_[0]->{_pushd})},fallback=>1;sub pushd {my ($target_dir,$options)=@_;$options->{untaint_pattern}||=qr{^([-+@\w./]+)$};$target_dir="." unless defined$target_dir;croak "Can't locate directory $target_dir" unless -d $target_dir;my$tainted_orig=getcwd;my$orig;if ($tainted_orig =~ $options->{untaint_pattern}){$orig=$1}else {$orig=$tainted_orig}my$tainted_dest;eval {$tainted_dest=$target_dir ? abs_path($target_dir): $orig};croak "Can't locate absolute path for $target_dir: $@" if $@;my$dest;if ($tainted_dest =~ $options->{untaint_pattern}){$dest=$1}else {$dest=$tainted_dest}if ($dest ne $orig){chdir$dest or croak "Can't chdir to $dest\: $!"}my$self=bless {_pushd=>$dest,_original=>$orig },__PACKAGE__;return$self}sub tempd {my ($options)=@_;my$dir;eval {$dir=pushd(File::Temp::tempdir(CLEANUP=>0),$options)};croak $@ if $@;$dir->{_tempd}=1;return$dir}sub preserve {my$self=shift;return 1 if!$self->{"_tempd"};if (@_==0){return$self->{_preserve}=1}else {return$self->{_preserve}=$_[0]? 1 : 0}}sub DESTROY {my ($self)=@_;my$orig=$self->{_original};chdir$orig if$orig;if ($self->{_tempd}&& !$self->{_preserve}){my$err=do {local $@;eval {rmtree($self->{_pushd})};$@};carp$err if$err}}1;
 FILE_PUSHD
 
-$fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
-  package HTTP::Tiny;use strict;use warnings;our$VERSION='0.034';use Carp ();my@attributes;BEGIN {@attributes=qw(cookie_jar default_headers local_address max_redirect max_size proxy no_proxy timeout SSL_options verify_SSL);no strict 'refs';for my$accessor (@attributes){*{$accessor}=sub {@_ > 1 ? $_[0]->{$accessor}=$_[1]: $_[0]->{$accessor}}}}sub agent {my($self,$agent)=@_;if(@_ > 1){$self->{agent}=(defined$agent && $agent =~ / $/)? $agent .$self->_agent : $agent}return$self->{agent}}sub new {my($class,%args)=@_;my$self={max_redirect=>5,timeout=>60,verify_SSL=>$args{verify_SSL}|| $args{verify_ssl}|| 0,no_proxy=>$ENV{no_proxy},};bless$self,$class;$class->_validate_cookie_jar($args{cookie_jar})if$args{cookie_jar};for my$key (@attributes){$self->{$key}=$args{$key}if exists$args{$key}}$self->agent(exists$args{agent}? $args{agent}: $class->_agent);if (!exists$self->{proxy}&& (my$http_proxy=$ENV{http_proxy})){if ($http_proxy =~ m{\Ahttp://[^/?#:@]+:\d+/?\z}){$self->{proxy}=$http_proxy}else {Carp::croak(qq{Environment 'http_proxy' must be in format http://<host>:<port>/\n})}}unless (ref$self->{no_proxy}eq 'ARRAY'){$self->{no_proxy}=(defined$self->{no_proxy})? [split /\s*,\s*/,$self->{no_proxy}]: []}return$self}for my$sub_name (qw/get head put post delete/){my$req_method=uc$sub_name;no strict 'refs';eval <<"HERE"}sub post_form {my ($self,$url,$data,$args)=@_;(@_==3 || @_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ ."\n");my$headers={};while (my ($key,$value)=each %{$args->{headers}|| {}}){$headers->{lc$key}=$value}delete$args->{headers};return$self->request('POST',$url,{%$args,content=>$self->www_form_urlencode($data),headers=>{%$headers,'content-type'=>'application/x-www-form-urlencoded' },})}sub mirror {my ($self,$url,$file,$args)=@_;@_==3 || (@_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ ."\n");if (-e $file and my$mtime=(stat($file))[9]){$args->{headers}{'if-modified-since'}||=$self->_http_date($mtime)}my$tempfile=$file .int(rand(2**31));open my$fh,">",$tempfile or Carp::croak(qq/Error: Could not open temporary file $tempfile for downloading: $!\n/);binmode$fh;$args->{data_callback}=sub {print {$fh}$_[0]};my$response=$self->request('GET',$url,$args);close$fh or Carp::croak(qq/Error: Could not close temporary file $tempfile: $!\n/);if ($response->{success}){rename$tempfile,$file or Carp::croak(qq/Error replacing $file with $tempfile: $!\n/);my$lm=$response->{headers}{'last-modified'};if ($lm and my$mtime=$self->_parse_http_date($lm)){utime$mtime,$mtime,$file}}$response->{success}||=$response->{status}eq '304';unlink$tempfile;return$response}my%idempotent=map {$_=>1}qw/GET HEAD PUT DELETE OPTIONS TRACE/;sub request {my ($self,$method,$url,$args)=@_;@_==3 || (@_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ ."\n");$args ||={};my$response;for (0 .. 1){$response=eval {$self->_request($method,$url,$args)};last unless $@ && $idempotent{$method}&& $@ =~ m{^(?:Socket closed|Unexpected end)}}if (my$e="$@"){$response={url=>$url,success=>q{},status=>599,reason=>'Internal Exception',content=>$e,headers=>{'content-type'=>'text/plain','content-length'=>length$e,}}}return$response}sub www_form_urlencode {my ($self,$data)=@_;(@_==2 && ref$data)or Carp::croak(q/Usage: $http->www_form_urlencode(DATAREF)/ ."\n");(ref$data eq 'HASH' || ref$data eq 'ARRAY')or Carp::croak("form data must be a hash or array reference\n");my@params=ref$data eq 'HASH' ? %$data : @$data;@params % 2==0 or Carp::croak("form data reference must have an even number of terms\n");my@terms;while(@params){my ($key,$value)=splice(@params,0,2);if (ref$value eq 'ARRAY'){unshift@params,map {$key=>$_}@$value}else {push@terms,join("=",map {$self->_uri_escape($_)}$key,$value)}}return join("&",sort@terms)}my%DefaultPort=(http=>80,https=>443,);sub _agent {my$class=ref($_[0])|| $_[0];(my$default_agent=$class)=~ s{::}{-}g;return$default_agent ."/" .($class->VERSION || 0)}sub _request {my ($self,$method,$url,$args)=@_;my ($scheme,$host,$port,$path_query,$auth)=$self->_split_url($url);my$request={method=>$method,scheme=>$scheme,host_port=>($port==$DefaultPort{$scheme}? $host : "$host:$port"),uri=>$path_query,headers=>{},};my$handle=HTTP::Tiny::Handle->new(timeout=>$self->{timeout},SSL_options=>$self->{SSL_options},verify_SSL=>$self->{verify_SSL},local_address=>$self->{local_address},);if ($self->{proxy}&&!grep {$host =~ /\Q$_\E$/}@{$self->{no_proxy}}){$request->{uri}="$scheme://$request->{host_port}$path_query";die(qq/HTTPS via proxy is not supported\n/)if$request->{scheme}eq 'https';$handle->connect(($self->_split_url($self->{proxy}))[0..2])}else {$handle->connect($scheme,$host,$port)}$self->_prepare_headers_and_cb($request,$args,$url,$auth);$handle->write_request($request);my$response;do {$response=$handle->read_response_header}until (substr($response->{status},0,1)ne '1');$self->_update_cookie_jar($url,$response)if$self->{cookie_jar};if (my@redir_args=$self->_maybe_redirect($request,$response,$args)){$handle->close;return$self->_request(@redir_args,$args)}if ($method eq 'HEAD' || $response->{status}=~ /^[23]04/){}else {my$data_cb=$self->_prepare_data_cb($response,$args);$handle->read_body($data_cb,$response)}$handle->close;$response->{success}=substr($response->{status},0,1)eq '2';$response->{url}=$url;return$response}sub _prepare_headers_and_cb {my ($self,$request,$args,$url,$auth)=@_;for ($self->{default_headers},$args->{headers}){next unless defined;while (my ($k,$v)=each %$_){$request->{headers}{lc$k}=$v}}$request->{headers}{'host'}=$request->{host_port};$request->{headers}{'connection'}="close";$request->{headers}{'user-agent'}||=$self->{agent};if (defined$args->{content}){if (ref$args->{content}eq 'CODE'){$request->{headers}{'content-type'}||="application/octet-stream";$request->{headers}{'transfer-encoding'}='chunked' unless$request->{headers}{'content-length'}|| $request->{headers}{'transfer-encoding'};$request->{cb}=$args->{content}}elsif (length$args->{content}){my$content=$args->{content};if ($] ge '5.008'){utf8::downgrade($content,1)or die(qq/Wide character in request message body\n/)}$request->{headers}{'content-type'}||="application/octet-stream";$request->{headers}{'content-length'}=length$content unless$request->{headers}{'content-length'}|| $request->{headers}{'transfer-encoding'};$request->{cb}=sub {substr$content,0,length$content,''}}$request->{trailer_cb}=$args->{trailer_callback}if ref$args->{trailer_callback}eq 'CODE'}if ($self->{cookie_jar}){my$cookies=$self->cookie_jar->cookie_header($url);$request->{headers}{cookie}=$cookies if length$cookies}if (length$auth &&!defined$request->{headers}{authentication}){require MIME::Base64;$request->{headers}{authorization}="Basic " .MIME::Base64::encode_base64($auth,"")}return}sub _prepare_data_cb {my ($self,$response,$args)=@_;my$data_cb=$args->{data_callback};$response->{content}='';if (!$data_cb || $response->{status}!~ /^2/){if (defined$self->{max_size}){$data_cb=sub {$_[1]->{content}.= $_[0];die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/)if length $_[1]->{content}> $self->{max_size}}}else {$data_cb=sub {$_[1]->{content}.= $_[0]}}}return$data_cb}sub _update_cookie_jar {my ($self,$url,$response)=@_;my$cookies=$response->{headers}->{'set-cookie'};return unless defined$cookies;my@cookies=ref$cookies ? @$cookies : $cookies;$self->cookie_jar->add($url,$_)for@cookies;return}sub _validate_cookie_jar {my ($class,$jar)=@_;for my$method (qw/add cookie_header/){Carp::croak(qq/Cookie jar must provide the '$method' method\n/)unless ref($jar)&& ref($jar)->can($method)}return}sub _maybe_redirect {my ($self,$request,$response,$args)=@_;my$headers=$response->{headers};my ($status,$method)=($response->{status},$request->{method});if (($status eq '303' or ($status =~ /^30[127]/ && $method =~ /^GET|HEAD$/))and $headers->{location}and ++$args->{redirects}<= $self->{max_redirect}){my$location=($headers->{location}=~ /^\//)? "$request->{scheme}://$request->{host_port}$headers->{location}" : $headers->{location};return (($status eq '303' ? 'GET' : $method),$location)}return}sub _split_url {my$url=pop;my ($scheme,$authority,$path_query)=$url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)> or die(qq/Cannot parse URL: '$url'\n/);$scheme=lc$scheme;$path_query="/$path_query" unless$path_query =~ m<\A/>;my ($auth,$host);$authority=(length($authority))? $authority : 'localhost';if ($authority =~ /@/){($auth,$host)=$authority =~ m/\A([^@]*)@(.*)\z/}else {$host=$authority;$auth=''}$host=lc$host;my$port=do {$host =~ s/:([0-9]*)\z// && length $1 ? $1 : ($scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef)};return ($scheme,$host,$port,$path_query,$auth)}my$DoW="Sun|Mon|Tue|Wed|Thu|Fri|Sat";my$MoY="Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";sub _http_date {my ($sec,$min,$hour,$mday,$mon,$year,$wday)=gmtime($_[1]);return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT",substr($DoW,$wday*4,3),$mday,substr($MoY,$mon*4,3),$year+1900,$hour,$min,$sec)}sub _parse_http_date {my ($self,$str)=@_;require Time::Local;my@tl_parts;if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/){@tl_parts=($6,$5,$4,$1,(index($MoY,$2)/4),$3)}elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/){@tl_parts=($6,$5,$4,$1,(index($MoY,$2)/4),$3)}elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/){@tl_parts=($5,$4,$3,$2,(index($MoY,$1)/4),$6)}return eval {my$t=@tl_parts ? Time::Local::timegm(@tl_parts): -1;$t < 0 ? undef : $t}}my%escapes=map {chr($_)=>sprintf("%%%02X",$_)}0..255;$escapes{' '}="+";my$unsafe_char=qr/[^A-Za-z0-9\-\._~]/;sub _uri_escape {my ($self,$str)=@_;if ($] ge '5.008'){utf8::encode($str)}else {$str=pack("U*",unpack("C*",$str))if (length$str==do {use bytes;length$str});$str=pack("C*",unpack("C*",$str))}$str =~ s/($unsafe_char)/$escapes{$1}/ge;return$str}package HTTP::Tiny::Handle;use strict;use warnings;use Errno qw[EINTR EPIPE];use IO::Socket qw[SOCK_STREAM];sub BUFSIZE () {32768}my$Printable=sub {local $_=shift;s/\r/\\r/g;s/\n/\\n/g;s/\t/\\t/g;s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge;$_};my$Token=qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;sub new {my ($class,%args)=@_;return bless {rbuf=>'',timeout=>60,max_line_size=>16384,max_header_lines=>64,verify_SSL=>0,SSL_options=>{},%args },$class}sub connect {@_==4 || die(q/Usage: $handle->connect(scheme, host, port)/ ."\n");my ($self,$scheme,$host,$port)=@_;if ($scheme eq 'https'){die(qq/IO::Socket::SSL 1.42 must be installed for https support\n/)unless eval {require IO::Socket::SSL;IO::Socket::SSL->VERSION(1.42)};die(qq/Net::SSLeay 1.49 must be installed for https support\n/)unless eval {require Net::SSLeay;Net::SSLeay->VERSION(1.49)}}elsif ($scheme ne 'http'){die(qq/Unsupported URL scheme '$scheme'\n/)}$self->{fh}='IO::Socket::INET'->new(PeerHost=>$host,PeerPort=>$port,$self->{local_address}? (LocalAddr=>$self->{local_address}): (),Proto=>'tcp',Type=>SOCK_STREAM,Timeout=>$self->{timeout})or die(qq/Could not connect to '$host:$port': $@\n/);binmode($self->{fh})or die(qq/Could not binmode() socket: '$!'\n/);if ($scheme eq 'https'){my$ssl_args=$self->_ssl_args($host);IO::Socket::SSL->start_SSL($self->{fh},%$ssl_args,SSL_create_ctx_callback=>sub {my$ctx=shift;Net::SSLeay::CTX_set_mode($ctx,Net::SSLeay::MODE_AUTO_RETRY())},);unless (ref($self->{fh})eq 'IO::Socket::SSL'){my$ssl_err=IO::Socket::SSL->errstr;die(qq/SSL connection failed for $host: $ssl_err\n/)}}$self->{host}=$host;$self->{port}=$port;return$self}sub close {@_==1 || die(q/Usage: $handle->close()/ ."\n");my ($self)=@_;CORE::close($self->{fh})or die(qq/Could not close socket: '$!'\n/)}sub write {@_==2 || die(q/Usage: $handle->write(buf)/ ."\n");my ($self,$buf)=@_;if ($] ge '5.008'){utf8::downgrade($buf,1)or die(qq/Wide character in write()\n/)}my$len=length$buf;my$off=0;local$SIG{PIPE}='IGNORE';while (){$self->can_write or die(qq/Timed out while waiting for socket to become ready for writing\n/);my$r=syswrite($self->{fh},$buf,$len,$off);if (defined$r){$len -= $r;$off += $r;last unless$len > 0}elsif ($!==EPIPE){die(qq/Socket closed by remote server: $!\n/)}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not write to SSL socket: '$err'\n /)}else {die(qq/Could not write to socket: '$!'\n/)}}}return$off}sub read {@_==2 || @_==3 || die(q/Usage: $handle->read(len [, allow_partial])/ ."\n");my ($self,$len,$allow_partial)=@_;my$buf='';my$got=length$self->{rbuf};if ($got){my$take=($got < $len)? $got : $len;$buf=substr($self->{rbuf},0,$take,'');$len -= $take}while ($len > 0){$self->can_read or die(q/Timed out while waiting for socket to become ready for reading/ ."\n");my$r=sysread($self->{fh},$buf,$len,length$buf);if (defined$r){last unless$r;$len -= $r}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not read from SSL socket: '$err'\n /)}else {die(qq/Could not read from socket: '$!'\n/)}}}if ($len &&!$allow_partial){die(qq/Unexpected end of stream\n/)}return$buf}sub readline {@_==1 || die(q/Usage: $handle->readline()/ ."\n");my ($self)=@_;while (){if ($self->{rbuf}=~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x){return $1}if (length$self->{rbuf}>= $self->{max_line_size}){die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/)}$self->can_read or die(qq/Timed out while waiting for socket to become ready for reading\n/);my$r=sysread($self->{fh},$self->{rbuf},BUFSIZE,length$self->{rbuf});if (defined$r){last unless$r}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not read from SSL socket: '$err'\n /)}else {die(qq/Could not read from socket: '$!'\n/)}}}die(qq/Unexpected end of stream while looking for line\n/)}sub read_header_lines {@_==1 || @_==2 || die(q/Usage: $handle->read_header_lines([headers])/ ."\n");my ($self,$headers)=@_;$headers ||={};my$lines=0;my$val;while (){my$line=$self->readline;if (++$lines >= $self->{max_header_lines}){die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/)}elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x){my ($field_name)=lc $1;if (exists$headers->{$field_name}){for ($headers->{$field_name}){$_=[$_]unless ref $_ eq "ARRAY";push @$_,$2;$val=\$_->[-1]}}else {$val=\($headers->{$field_name}=$2)}}elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x){$val or die(qq/Unexpected header continuation line\n/);next unless length $1;$$val .= ' ' if length $$val;$$val .= $1}elsif ($line =~ /\A \x0D?\x0A \z/x){last}else {die(q/Malformed header line: / .$Printable->($line)."\n")}}return$headers}sub write_request {@_==2 || die(q/Usage: $handle->write_request(request)/ ."\n");my($self,$request)=@_;$self->write_request_header(@{$request}{qw/method uri headers/});$self->write_body($request)if$request->{cb};return}my%HeaderCase=('content-md5'=>'Content-MD5','etag'=>'ETag','te'=>'TE','www-authenticate'=>'WWW-Authenticate','x-xss-protection'=>'X-XSS-Protection',);sub write_header_lines {(@_==2 && ref $_[1]eq 'HASH')|| die(q/Usage: $handle->write_header_lines(headers)/ ."\n");my($self,$headers)=@_;my$buf='';while (my ($k,$v)=each %$headers){my$field_name=lc$k;if (exists$HeaderCase{$field_name}){$field_name=$HeaderCase{$field_name}}else {$field_name =~ /\A $Token+ \z/xo or die(q/Invalid HTTP header field name: / .$Printable->($field_name)."\n");$field_name =~ s/\b(\w)/\u$1/g;$HeaderCase{lc$field_name}=$field_name}for (ref$v eq 'ARRAY' ? @$v : $v){/[^\x0D\x0A]/ or die(qq/Invalid HTTP header field value ($field_name): / .$Printable->($_)."\n");$buf .= "$field_name: $_\x0D\x0A"}}$buf .= "\x0D\x0A";return$self->write($buf)}sub read_body {@_==3 || die(q/Usage: $handle->read_body(callback, response)/ ."\n");my ($self,$cb,$response)=@_;my$te=$response->{headers}{'transfer-encoding'}|| '';if (grep {/chunked/i}(ref$te eq 'ARRAY' ? @$te : $te)){$self->read_chunked_body($cb,$response)}else {$self->read_content_body($cb,$response)}return}sub write_body {@_==2 || die(q/Usage: $handle->write_body(request)/ ."\n");my ($self,$request)=@_;if ($request->{headers}{'content-length'}){return$self->write_content_body($request)}else {return$self->write_chunked_body($request)}}sub read_content_body {@_==3 || @_==4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ ."\n");my ($self,$cb,$response,$content_length)=@_;$content_length ||=$response->{headers}{'content-length'};if (defined$content_length){my$len=$content_length;while ($len > 0){my$read=($len > BUFSIZE)? BUFSIZE : $len;$cb->($self->read($read,0),$response);$len -= $read}}else {my$chunk;$cb->($chunk,$response)while length($chunk=$self->read(BUFSIZE,1))}return}sub write_content_body {@_==2 || die(q/Usage: $handle->write_content_body(request)/ ."\n");my ($self,$request)=@_;my ($len,$content_length)=(0,$request->{headers}{'content-length'});while (){my$data=$request->{cb}->();defined$data && length$data or last;if ($] ge '5.008'){utf8::downgrade($data,1)or die(qq/Wide character in write_content()\n/)}$len += $self->write($data)}$len==$content_length or die(qq/Content-Length missmatch (got: $len expected: $content_length)\n/);return$len}sub read_chunked_body {@_==3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ ."\n");my ($self,$cb,$response)=@_;while (){my$head=$self->readline;$head =~ /\A ([A-Fa-f0-9]+)/x or die(q/Malformed chunk head: / .$Printable->($head)."\n");my$len=hex($1)or last;$self->read_content_body($cb,$response,$len);$self->read(2)eq "\x0D\x0A" or die(qq/Malformed chunk: missing CRLF after chunk data\n/)}$self->read_header_lines($response->{headers});return}sub write_chunked_body {@_==2 || die(q/Usage: $handle->write_chunked_body(request)/ ."\n");my ($self,$request)=@_;my$len=0;while (){my$data=$request->{cb}->();defined$data && length$data or last;if ($] ge '5.008'){utf8::downgrade($data,1)or die(qq/Wide character in write_chunked_body()\n/)}$len += length$data;my$chunk=sprintf '%X',length$data;$chunk .= "\x0D\x0A";$chunk .= $data;$chunk .= "\x0D\x0A";$self->write($chunk)}$self->write("0\x0D\x0A");$self->write_header_lines($request->{trailer_cb}->())if ref$request->{trailer_cb}eq 'CODE';return$len}sub read_response_header {@_==1 || die(q/Usage: $handle->read_response_header()/ ."\n");my ($self)=@_;my$line=$self->readline;$line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) [\x09\x20]+ ([^\x0D\x0A]*) \x0D?\x0A/x or die(q/Malformed Status-Line: / .$Printable->($line)."\n");my ($protocol,$version,$status,$reason)=($1,$2,$3,$4);die (qq/Unsupported HTTP protocol: $protocol\n/)unless$version =~ /0*1\.0*[01]/;return {status=>$status,reason=>$reason,headers=>$self->read_header_lines,protocol=>$protocol,}}sub write_request_header {@_==4 || die(q/Usage: $handle->write_request_header(method, request_uri, headers)/ ."\n");my ($self,$method,$request_uri,$headers)=@_;return$self->write("$method $request_uri HTTP/1.1\x0D\x0A")+ $self->write_header_lines($headers)}sub _do_timeout {my ($self,$type,$timeout)=@_;$timeout=$self->{timeout}unless defined$timeout && $timeout >= 0;my$fd=fileno$self->{fh};defined$fd && $fd >= 0 or die(qq/select(2): 'Bad file descriptor'\n/);my$initial=time;my$pending=$timeout;my$nfound;vec(my$fdset='',$fd,1)=1;while (){$nfound=($type eq 'read')? select($fdset,undef,undef,$pending): select(undef,$fdset,undef,$pending);if ($nfound==-1){$!==EINTR or die(qq/select(2): '$!'\n/);redo if!$timeout || ($pending=$timeout - (time - $initial))> 0;$nfound=0}last}$!=0;return$nfound}sub can_read {@_==1 || @_==2 || die(q/Usage: $handle->can_read([timeout])/ ."\n");my$self=shift;return$self->_do_timeout('read',@_)}sub can_write {@_==1 || @_==2 || die(q/Usage: $handle->can_write([timeout])/ ."\n");my$self=shift;return$self->_do_timeout('write',@_)}sub _find_CA_file {my$self=shift();return$self->{SSL_options}->{SSL_ca_file}if$self->{SSL_options}->{SSL_ca_file}and -e $self->{SSL_options}->{SSL_ca_file};return Mozilla::CA::SSL_ca_file()if eval {require Mozilla::CA};for my$ca_bundle (qw{/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/ca-bundle.pem}){return$ca_bundle if -e $ca_bundle}die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/ .qq/Try installing Mozilla::CA from CPAN\n/}sub _ssl_args {my ($self,$host)=@_;my%ssl_args;if (Net::SSLeay::OPENSSL_VERSION_NUMBER()>= 0x01000000){$ssl_args{SSL_hostname}=$host,}if ($self->{verify_SSL}){$ssl_args{SSL_verifycn_scheme}='http';$ssl_args{SSL_verifycn_name}=$host;$ssl_args{SSL_verify_mode}=0x01;$ssl_args{SSL_ca_file}=$self->_find_CA_file}else {$ssl_args{SSL_verifycn_scheme}='none';$ssl_args{SSL_verify_mode}=0x00}for my$k (keys %{$self->{SSL_options}}){$ssl_args{$k}=$self->{SSL_options}{$k}if$k =~ m/^SSL_/}return \%ssl_args}1;
+$fatpacked{"HTTP/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'HTTP_TINY';
+  package HTTP::Tiny;use strict;use warnings;our$VERSION='0.043';use Carp ();my@attributes;BEGIN {@attributes=qw(cookie_jar default_headers http_proxy https_proxy keep_alive local_address max_redirect max_size proxy no_proxy timeout SSL_options verify_SSL);my%persist_ok=map {;$_=>1}qw(cookie_jar default_headers max_redirect max_size);no strict 'refs';no warnings 'uninitialized';for my$accessor (@attributes){*{$accessor}=sub {@_ > 1 ? do {delete $_[0]->{handle}if!$persist_ok{$accessor}&& $_[1]ne $_[0]->{$accessor};$_[0]->{$accessor}=$_[1]}: $_[0]->{$accessor}}}}sub agent {my($self,$agent)=@_;if(@_ > 1){$self->{agent}=(defined$agent && $agent =~ / $/)? $agent .$self->_agent : $agent}return$self->{agent}}sub new {my($class,%args)=@_;my$self={max_redirect=>5,timeout=>60,keep_alive=>1,verify_SSL=>$args{verify_SSL}|| $args{verify_ssl}|| 0,no_proxy=>$ENV{no_proxy},};bless$self,$class;$class->_validate_cookie_jar($args{cookie_jar})if$args{cookie_jar};for my$key (@attributes){$self->{$key}=$args{$key}if exists$args{$key}}$self->agent(exists$args{agent}? $args{agent}: $class->_agent);$self->_set_proxies;return$self}sub _set_proxies {my ($self)=@_;if (!$self->{proxy}){$self->{proxy}=$ENV{all_proxy}|| $ENV{ALL_PROXY};if (defined$self->{proxy}){$self->_split_proxy('generic proxy'=>$self->{proxy})}else {delete$self->{proxy}}}if (!$self->{http_proxy}){$self->{http_proxy}=$ENV{http_proxy}|| $self->{proxy};if (defined$self->{http_proxy}){$self->_split_proxy(http_proxy=>$self->{http_proxy});$self->{_has_proxy}{http}=1}else {delete$self->{http_proxy}}}if (!$self->{https_proxy}){$self->{https_proxy}=$ENV{https_proxy}|| $ENV{HTTPS_PROXY}|| $self->{proxy};if ($self->{https_proxy}){$self->_split_proxy(https_proxy=>$self->{https_proxy});$self->{_has_proxy}{https}=1}else {delete$self->{https_proxy}}}unless (ref$self->{no_proxy}eq 'ARRAY'){$self->{no_proxy}=(defined$self->{no_proxy})? [split /\s*,\s*/,$self->{no_proxy}]: []}return}for my$sub_name (qw/get head put post delete/){my$req_method=uc$sub_name;no strict 'refs';eval <<"HERE"}sub post_form {my ($self,$url,$data,$args)=@_;(@_==3 || @_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ ."\n");my$headers={};while (my ($key,$value)=each %{$args->{headers}|| {}}){$headers->{lc$key}=$value}delete$args->{headers};return$self->request('POST',$url,{%$args,content=>$self->www_form_urlencode($data),headers=>{%$headers,'content-type'=>'application/x-www-form-urlencoded' },})}sub mirror {my ($self,$url,$file,$args)=@_;@_==3 || (@_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ ."\n");if (-e $file and my$mtime=(stat($file))[9]){$args->{headers}{'if-modified-since'}||=$self->_http_date($mtime)}my$tempfile=$file .int(rand(2**31));require Fcntl;sysopen my$fh,$tempfile,Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY()or Carp::croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/);binmode$fh;$args->{data_callback}=sub {print {$fh}$_[0]};my$response=$self->request('GET',$url,$args);close$fh or Carp::croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/);if ($response->{success}){rename$tempfile,$file or Carp::croak(qq/Error replacing $file with $tempfile: $!\n/);my$lm=$response->{headers}{'last-modified'};if ($lm and my$mtime=$self->_parse_http_date($lm)){utime$mtime,$mtime,$file}}$response->{success}||=$response->{status}eq '304';unlink$tempfile;return$response}my%idempotent=map {$_=>1}qw/GET HEAD PUT DELETE OPTIONS TRACE/;sub request {my ($self,$method,$url,$args)=@_;@_==3 || (@_==4 && ref$args eq 'HASH')or Carp::croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ ."\n");$args ||={};my$response;for (0 .. 1){$response=eval {$self->_request($method,$url,$args)};last unless $@ && $idempotent{$method}&& $@ =~ m{^(?:Socket closed|Unexpected end)}}if (my$e=$@){if (ref$e eq 'HASH' && exists$e->{status}){return$e}$e="$e";$response={url=>$url,success=>q{},status=>599,reason=>'Internal Exception',content=>$e,headers=>{'content-type'=>'text/plain','content-length'=>length$e,}}}return$response}sub www_form_urlencode {my ($self,$data)=@_;(@_==2 && ref$data)or Carp::croak(q/Usage: $http->www_form_urlencode(DATAREF)/ ."\n");(ref$data eq 'HASH' || ref$data eq 'ARRAY')or Carp::croak("form data must be a hash or array reference\n");my@params=ref$data eq 'HASH' ? %$data : @$data;@params % 2==0 or Carp::croak("form data reference must have an even number of terms\n");my@terms;while(@params){my ($key,$value)=splice(@params,0,2);if (ref$value eq 'ARRAY'){unshift@params,map {$key=>$_}@$value}else {push@terms,join("=",map {$self->_uri_escape($_)}$key,$value)}}return join("&",(ref$data eq 'ARRAY')? (@terms): (sort@terms))}my%DefaultPort=(http=>80,https=>443,);sub _agent {my$class=ref($_[0])|| $_[0];(my$default_agent=$class)=~ s{::}{-}g;return$default_agent ."/" .($class->VERSION || 0)}sub _request {my ($self,$method,$url,$args)=@_;my ($scheme,$host,$port,$path_query,$auth)=$self->_split_url($url);my$request={method=>$method,scheme=>$scheme,host=>$host,host_port=>($port==$DefaultPort{$scheme}? $host : "$host:$port"),uri=>$path_query,headers=>{},};my$handle=delete$self->{handle};if ($handle){unless ($handle->can_reuse($scheme,$host,$port)){$handle->close;undef$handle}}$handle ||=$self->_open_handle($request,$scheme,$host,$port);$self->_prepare_headers_and_cb($request,$args,$url,$auth);$handle->write_request($request);my$response;do {$response=$handle->read_response_header}until (substr($response->{status},0,1)ne '1');$self->_update_cookie_jar($url,$response)if$self->{cookie_jar};if (my@redir_args=$self->_maybe_redirect($request,$response,$args)){$handle->close;return$self->_request(@redir_args,$args)}my$known_message_length;if ($method eq 'HEAD' || $response->{status}=~ /^[23]04/){$known_message_length=1}else {my$data_cb=$self->_prepare_data_cb($response,$args);$known_message_length=$handle->read_body($data_cb,$response)}if ($self->{keep_alive}&& $known_message_length && $response->{protocol}eq 'HTTP/1.1' && ($response->{headers}{connection}|| '')ne 'close'){$self->{handle}=$handle}else {$handle->close}$response->{success}=substr($response->{status},0,1)eq '2';$response->{url}=$url;return$response}sub _open_handle {my ($self,$request,$scheme,$host,$port)=@_;my$handle=HTTP::Tiny::Handle->new(timeout=>$self->{timeout},SSL_options=>$self->{SSL_options},verify_SSL=>$self->{verify_SSL},local_address=>$self->{local_address},keep_alive=>$self->{keep_alive});if ($self->{_has_proxy}{$scheme}&&!grep {$host =~ /\Q$_\E$/}@{$self->{no_proxy}}){return$self->_proxy_connect($request,$handle)}else {return$handle->connect($scheme,$host,$port)}}sub _proxy_connect {my ($self,$request,$handle)=@_;my@proxy_vars;if ($request->{scheme}eq 'https'){Carp::croak(qq{No https_proxy defined})unless$self->{https_proxy};@proxy_vars=$self->_split_proxy(https_proxy=>$self->{https_proxy});if ($proxy_vars[0]eq 'https'){Carp::croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}})}}else {Carp::croak(qq{No http_proxy defined})unless$self->{http_proxy};@proxy_vars=$self->_split_proxy(http_proxy=>$self->{http_proxy})}my ($p_scheme,$p_host,$p_port,$p_auth)=@proxy_vars;if (length$p_auth &&!defined$request->{headers}{'proxy-authorization'}){$self->_add_basic_auth_header($request,'proxy-authorization'=>$p_auth)}$handle->connect($p_scheme,$p_host,$p_port);if ($request->{scheme}eq 'https'){$self->_create_proxy_tunnel($request,$handle)}else {$request->{uri}="$request->{scheme}://$request->{host_port}$request->{uri}"}return$handle}sub _split_proxy {my ($self,$type,$proxy)=@_;my ($scheme,$host,$port,$path_query,$auth)=eval {$self->_split_url($proxy)};unless(defined($scheme)&& length($scheme)&& length($host)&& length($port)&& $path_query eq '/'){Carp::croak(qq{$type URL must be in format http[s]://[auth@]<host>:<port>/\n})}return ($scheme,$host,$port,$auth)}sub _create_proxy_tunnel {my ($self,$request,$handle)=@_;$handle->_assert_ssl;my$agent=exists($request->{headers}{'user-agent'})? $request->{headers}{'user-agent'}: $self->{agent};my$connect_request={method=>'CONNECT',uri=>$request->{host_port},headers=>{host=>$request->{host_port},'user-agent'=>$agent,}};if ($request->{headers}{'proxy-authorization'}){$connect_request->{headers}{'proxy-authorization'}=delete$request->{headers}{'proxy-authorization'}}$handle->write_request($connect_request);my$response;do {$response=$handle->read_response_header}until (substr($response->{status},0,1)ne '1');unless (substr($response->{status},0,1)eq '2'){die$response}$handle->start_ssl($request->{host});return}sub _prepare_headers_and_cb {my ($self,$request,$args,$url,$auth)=@_;for ($self->{default_headers},$args->{headers}){next unless defined;while (my ($k,$v)=each %$_){$request->{headers}{lc$k}=$v}}$request->{headers}{'host'}=$request->{host_port};$request->{headers}{'user-agent'}||=$self->{agent};$request->{headers}{'connection'}="close" unless$self->{keep_alive};if (defined$args->{content}){if (ref$args->{content}eq 'CODE'){$request->{headers}{'content-type'}||="application/octet-stream";$request->{headers}{'transfer-encoding'}='chunked' unless$request->{headers}{'content-length'}|| $request->{headers}{'transfer-encoding'};$request->{cb}=$args->{content}}elsif (length$args->{content}){my$content=$args->{content};if ($] ge '5.008'){utf8::downgrade($content,1)or die(qq/Wide character in request message body\n/)}$request->{headers}{'content-type'}||="application/octet-stream";$request->{headers}{'content-length'}=length$content unless$request->{headers}{'content-length'}|| $request->{headers}{'transfer-encoding'};$request->{cb}=sub {substr$content,0,length$content,''}}$request->{trailer_cb}=$args->{trailer_callback}if ref$args->{trailer_callback}eq 'CODE'}if ($self->{cookie_jar}){my$cookies=$self->cookie_jar->cookie_header($url);$request->{headers}{cookie}=$cookies if length$cookies}if (length$auth &&!defined$request->{headers}{authorization}){$self->_add_basic_auth_header($request,'authorization'=>$auth)}return}sub _add_basic_auth_header {my ($self,$request,$header,$auth)=@_;require MIME::Base64;$request->{headers}{$header}="Basic " .MIME::Base64::encode_base64($auth,"");return}sub _prepare_data_cb {my ($self,$response,$args)=@_;my$data_cb=$args->{data_callback};$response->{content}='';if (!$data_cb || $response->{status}!~ /^2/){if (defined$self->{max_size}){$data_cb=sub {$_[1]->{content}.= $_[0];die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/)if length $_[1]->{content}> $self->{max_size}}}else {$data_cb=sub {$_[1]->{content}.= $_[0]}}}return$data_cb}sub _update_cookie_jar {my ($self,$url,$response)=@_;my$cookies=$response->{headers}->{'set-cookie'};return unless defined$cookies;my@cookies=ref$cookies ? @$cookies : $cookies;$self->cookie_jar->add($url,$_)for@cookies;return}sub _validate_cookie_jar {my ($class,$jar)=@_;for my$method (qw/add cookie_header/){Carp::croak(qq/Cookie jar must provide the '$method' method\n/)unless ref($jar)&& ref($jar)->can($method)}return}sub _maybe_redirect {my ($self,$request,$response,$args)=@_;my$headers=$response->{headers};my ($status,$method)=($response->{status},$request->{method});if (($status eq '303' or ($status =~ /^30[127]/ && $method =~ /^GET|HEAD$/))and $headers->{location}and ++$args->{redirects}<= $self->{max_redirect}){my$location=($headers->{location}=~ /^\//)? "$request->{scheme}://$request->{host_port}$headers->{location}" : $headers->{location};return (($status eq '303' ? 'GET' : $method),$location)}return}sub _split_url {my$url=pop;my ($scheme,$authority,$path_query)=$url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)> or die(qq/Cannot parse URL: '$url'\n/);$scheme=lc$scheme;$path_query="/$path_query" unless$path_query =~ m<\A/>;my ($auth,$host);$authority=(length($authority))? $authority : 'localhost';if ($authority =~ /@/){($auth,$host)=$authority =~ m/\A([^@]*)@(.*)\z/;$auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg}else {$host=$authority;$auth=''}$host=lc$host;my$port=do {$host =~ s/:([0-9]*)\z// && length $1 ? $1 : ($scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef)};return ($scheme,$host,$port,$path_query,$auth)}my$DoW="Sun|Mon|Tue|Wed|Thu|Fri|Sat";my$MoY="Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";sub _http_date {my ($sec,$min,$hour,$mday,$mon,$year,$wday)=gmtime($_[1]);return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT",substr($DoW,$wday*4,3),$mday,substr($MoY,$mon*4,3),$year+1900,$hour,$min,$sec)}sub _parse_http_date {my ($self,$str)=@_;require Time::Local;my@tl_parts;if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/){@tl_parts=($6,$5,$4,$1,(index($MoY,$2)/4),$3)}elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/){@tl_parts=($6,$5,$4,$1,(index($MoY,$2)/4),$3)}elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/){@tl_parts=($5,$4,$3,$2,(index($MoY,$1)/4),$6)}return eval {my$t=@tl_parts ? Time::Local::timegm(@tl_parts): -1;$t < 0 ? undef : $t}}my%escapes=map {chr($_)=>sprintf("%%%02X",$_)}0..255;$escapes{' '}="+";my$unsafe_char=qr/[^A-Za-z0-9\-\._~]/;sub _uri_escape {my ($self,$str)=@_;if ($] ge '5.008'){utf8::encode($str)}else {$str=pack("U*",unpack("C*",$str))if (length$str==do {use bytes;length$str});$str=pack("C*",unpack("C*",$str))}$str =~ s/($unsafe_char)/$escapes{$1}/ge;return$str}package HTTP::Tiny::Handle;use strict;use warnings;use Errno qw[EINTR EPIPE];use IO::Socket qw[SOCK_STREAM];my$SOCKET_CLASS=$ENV{PERL_HTTP_TINY_IPV4_ONLY}? 'IO::Socket::INET' : eval {require IO::Socket::IP;IO::Socket::IP->VERSION(0.25)}? 'IO::Socket::IP' : 'IO::Socket::INET';sub BUFSIZE () {32768}my$Printable=sub {local $_=shift;s/\r/\\r/g;s/\n/\\n/g;s/\t/\\t/g;s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge;$_};my$Token=qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;sub new {my ($class,%args)=@_;return bless {rbuf=>'',timeout=>60,max_line_size=>16384,max_header_lines=>64,verify_SSL=>0,SSL_options=>{},%args },$class}sub connect {@_==4 || die(q/Usage: $handle->connect(scheme, host, port)/ ."\n");my ($self,$scheme,$host,$port)=@_;if ($scheme eq 'https'){$self->_assert_ssl}elsif ($scheme ne 'http'){die(qq/Unsupported URL scheme '$scheme'\n/)}$self->{fh}=$SOCKET_CLASS->new(PeerHost=>$host,PeerPort=>$port,$self->{local_address}? (LocalAddr=>$self->{local_address}): (),Proto=>'tcp',Type=>SOCK_STREAM,Timeout=>$self->{timeout},KeepAlive=>!!$self->{keep_alive})or die(qq/Could not connect to '$host:$port': $@\n/);binmode($self->{fh})or die(qq/Could not binmode() socket: '$!'\n/);$self->start_ssl($host)if$scheme eq 'https';$self->{scheme}=$scheme;$self->{host}=$host;$self->{port}=$port;return$self}sub start_ssl {my ($self,$host)=@_;if (ref($self->{fh})eq 'IO::Socket::SSL'){unless ($self->{fh}->stop_SSL){my$ssl_err=IO::Socket::SSL->errstr;die(qq/Error halting prior SSL connection: $ssl_err/)}}my$ssl_args=$self->_ssl_args($host);IO::Socket::SSL->start_SSL($self->{fh},%$ssl_args,SSL_create_ctx_callback=>sub {my$ctx=shift;Net::SSLeay::CTX_set_mode($ctx,Net::SSLeay::MODE_AUTO_RETRY())},);unless (ref($self->{fh})eq 'IO::Socket::SSL'){my$ssl_err=IO::Socket::SSL->errstr;die(qq/SSL connection failed for $host: $ssl_err\n/)}}sub close {@_==1 || die(q/Usage: $handle->close()/ ."\n");my ($self)=@_;CORE::close($self->{fh})or die(qq/Could not close socket: '$!'\n/)}sub write {@_==2 || die(q/Usage: $handle->write(buf)/ ."\n");my ($self,$buf)=@_;if ($] ge '5.008'){utf8::downgrade($buf,1)or die(qq/Wide character in write()\n/)}my$len=length$buf;my$off=0;local$SIG{PIPE}='IGNORE';while (){$self->can_write or die(qq/Timed out while waiting for socket to become ready for writing\n/);my$r=syswrite($self->{fh},$buf,$len,$off);if (defined$r){$len -= $r;$off += $r;last unless$len > 0}elsif ($!==EPIPE){die(qq/Socket closed by remote server: $!\n/)}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not write to SSL socket: '$err'\n /)}else {die(qq/Could not write to socket: '$!'\n/)}}}return$off}sub read {@_==2 || @_==3 || die(q/Usage: $handle->read(len [, allow_partial])/ ."\n");my ($self,$len,$allow_partial)=@_;my$buf='';my$got=length$self->{rbuf};if ($got){my$take=($got < $len)? $got : $len;$buf=substr($self->{rbuf},0,$take,'');$len -= $take}while ($len > 0){$self->can_read or die(q/Timed out while waiting for socket to become ready for reading/ ."\n");my$r=sysread($self->{fh},$buf,$len,length$buf);if (defined$r){last unless$r;$len -= $r}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not read from SSL socket: '$err'\n /)}else {die(qq/Could not read from socket: '$!'\n/)}}}if ($len &&!$allow_partial){die(qq/Unexpected end of stream\n/)}return$buf}sub readline {@_==1 || die(q/Usage: $handle->readline()/ ."\n");my ($self)=@_;while (){if ($self->{rbuf}=~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x){return $1}if (length$self->{rbuf}>= $self->{max_line_size}){die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/)}$self->can_read or die(qq/Timed out while waiting for socket to become ready for reading\n/);my$r=sysread($self->{fh},$self->{rbuf},BUFSIZE,length$self->{rbuf});if (defined$r){last unless$r}elsif ($!!=EINTR){if ($self->{fh}->can('errstr')){my$err=$self->{fh}->errstr();die (qq/Could not read from SSL socket: '$err'\n /)}else {die(qq/Could not read from socket: '$!'\n/)}}}die(qq/Unexpected end of stream while looking for line\n/)}sub read_header_lines {@_==1 || @_==2 || die(q/Usage: $handle->read_header_lines([headers])/ ."\n");my ($self,$headers)=@_;$headers ||={};my$lines=0;my$val;while (){my$line=$self->readline;if (++$lines >= $self->{max_header_lines}){die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/)}elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x){my ($field_name)=lc $1;if (exists$headers->{$field_name}){for ($headers->{$field_name}){$_=[$_]unless ref $_ eq "ARRAY";push @$_,$2;$val=\$_->[-1]}}else {$val=\($headers->{$field_name}=$2)}}elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x){$val or die(qq/Unexpected header continuation line\n/);next unless length $1;$$val .= ' ' if length $$val;$$val .= $1}elsif ($line =~ /\A \x0D?\x0A \z/x){last}else {die(q/Malformed header line: / .$Printable->($line)."\n")}}return$headers}sub write_request {@_==2 || die(q/Usage: $handle->write_request(request)/ ."\n");my($self,$request)=@_;$self->write_request_header(@{$request}{qw/method uri headers/});$self->write_body($request)if$request->{cb};return}my%HeaderCase=('content-md5'=>'Content-MD5','etag'=>'ETag','te'=>'TE','www-authenticate'=>'WWW-Authenticate','x-xss-protection'=>'X-XSS-Protection',);sub write_header_lines {(@_==2 || @_==3 && ref $_[1]eq 'HASH')|| die(q/Usage: $handle->write_header_lines(headers[,prefix])/ ."\n");my($self,$headers,$prefix_data)=@_;my$buf=(defined$prefix_data ? $prefix_data : '');while (my ($k,$v)=each %$headers){my$field_name=lc$k;if (exists$HeaderCase{$field_name}){$field_name=$HeaderCase{$field_name}}else {$field_name =~ /\A $Token+ \z/xo or die(q/Invalid HTTP header field name: / .$Printable->($field_name)."\n");$field_name =~ s/\b(\w)/\u$1/g;$HeaderCase{lc$field_name}=$field_name}for (ref$v eq 'ARRAY' ? @$v : $v){/[^\x0D\x0A]/ or die(qq/Invalid HTTP header field value ($field_name): / .$Printable->($_)."\n");$buf .= "$field_name: $_\x0D\x0A"}}$buf .= "\x0D\x0A";return$self->write($buf)}sub read_body {@_==3 || die(q/Usage: $handle->read_body(callback, response)/ ."\n");my ($self,$cb,$response)=@_;my$te=$response->{headers}{'transfer-encoding'}|| '';my$chunked=grep {/chunked/i}(ref$te eq 'ARRAY' ? @$te : $te);return$chunked ? $self->read_chunked_body($cb,$response): $self->read_content_body($cb,$response)}sub write_body {@_==2 || die(q/Usage: $handle->write_body(request)/ ."\n");my ($self,$request)=@_;if ($request->{headers}{'content-length'}){return$self->write_content_body($request)}else {return$self->write_chunked_body($request)}}sub read_content_body {@_==3 || @_==4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ ."\n");my ($self,$cb,$response,$content_length)=@_;$content_length ||=$response->{headers}{'content-length'};if (defined$content_length){my$len=$content_length;while ($len > 0){my$read=($len > BUFSIZE)? BUFSIZE : $len;$cb->($self->read($read,0),$response);$len -= $read}return length($self->{rbuf})==0}my$chunk;$cb->($chunk,$response)while length($chunk=$self->read(BUFSIZE,1));return}sub write_content_body {@_==2 || die(q/Usage: $handle->write_content_body(request)/ ."\n");my ($self,$request)=@_;my ($len,$content_length)=(0,$request->{headers}{'content-length'});while (){my$data=$request->{cb}->();defined$data && length$data or last;if ($] ge '5.008'){utf8::downgrade($data,1)or die(qq/Wide character in write_content()\n/)}$len += $self->write($data)}$len==$content_length or die(qq/Content-Length missmatch (got: $len expected: $content_length)\n/);return$len}sub read_chunked_body {@_==3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ ."\n");my ($self,$cb,$response)=@_;while (){my$head=$self->readline;$head =~ /\A ([A-Fa-f0-9]+)/x or die(q/Malformed chunk head: / .$Printable->($head)."\n");my$len=hex($1)or last;$self->read_content_body($cb,$response,$len);$self->read(2)eq "\x0D\x0A" or die(qq/Malformed chunk: missing CRLF after chunk data\n/)}$self->read_header_lines($response->{headers});return 1}sub write_chunked_body {@_==2 || die(q/Usage: $handle->write_chunked_body(request)/ ."\n");my ($self,$request)=@_;my$len=0;while (){my$data=$request->{cb}->();defined$data && length$data or last;if ($] ge '5.008'){utf8::downgrade($data,1)or die(qq/Wide character in write_chunked_body()\n/)}$len += length$data;my$chunk=sprintf '%X',length$data;$chunk .= "\x0D\x0A";$chunk .= $data;$chunk .= "\x0D\x0A";$self->write($chunk)}$self->write("0\x0D\x0A");$self->write_header_lines($request->{trailer_cb}->())if ref$request->{trailer_cb}eq 'CODE';return$len}sub read_response_header {@_==1 || die(q/Usage: $handle->read_response_header()/ ."\n");my ($self)=@_;my$line=$self->readline;$line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) [\x09\x20]+ ([^\x0D\x0A]*) \x0D?\x0A/x or die(q/Malformed Status-Line: / .$Printable->($line)."\n");my ($protocol,$version,$status,$reason)=($1,$2,$3,$4);die (qq/Unsupported HTTP protocol: $protocol\n/)unless$version =~ /0*1\.0*[01]/;return {status=>$status,reason=>$reason,headers=>$self->read_header_lines,protocol=>$protocol,}}sub write_request_header {@_==4 || die(q/Usage: $handle->write_request_header(method, request_uri, headers)/ ."\n");my ($self,$method,$request_uri,$headers)=@_;return$self->write_header_lines($headers,"$method $request_uri HTTP/1.1\x0D\x0A")}sub _do_timeout {my ($self,$type,$timeout)=@_;$timeout=$self->{timeout}unless defined$timeout && $timeout >= 0;my$fd=fileno$self->{fh};defined$fd && $fd >= 0 or die(qq/select(2): 'Bad file descriptor'\n/);my$initial=time;my$pending=$timeout;my$nfound;vec(my$fdset='',$fd,1)=1;while (){$nfound=($type eq 'read')? select($fdset,undef,undef,$pending): select(undef,$fdset,undef,$pending);if ($nfound==-1){$!==EINTR or die(qq/select(2): '$!'\n/);redo if!$timeout || ($pending=$timeout - (time - $initial))> 0;$nfound=0}last}$!=0;return$nfound}sub can_read {@_==1 || @_==2 || die(q/Usage: $handle->can_read([timeout])/ ."\n");my$self=shift;if (ref($self->{fh})eq 'IO::Socket::SSL'){return 1 if$self->{fh}->pending}return$self->_do_timeout('read',@_)}sub can_write {@_==1 || @_==2 || die(q/Usage: $handle->can_write([timeout])/ ."\n");my$self=shift;return$self->_do_timeout('write',@_)}sub _assert_ssl {die(qq/IO::Socket::SSL 1.42 must be installed for https support\n/)unless eval {require IO::Socket::SSL;IO::Socket::SSL->VERSION(1.42)};die(qq/Net::SSLeay 1.49 must be installed for https support\n/)unless eval {require Net::SSLeay;Net::SSLeay->VERSION(1.49)}}sub can_reuse {my ($self,$scheme,$host,$port)=@_;return 0 if length($self->{rbuf})|| $scheme ne $self->{scheme}|| $host ne $self->{host}|| $port ne $self->{port}|| eval {$self->can_read(0)}|| $@ ;return 1}sub _find_CA_file {my$self=shift();return$self->{SSL_options}->{SSL_ca_file}if$self->{SSL_options}->{SSL_ca_file}and -e $self->{SSL_options}->{SSL_ca_file};return Mozilla::CA::SSL_ca_file()if eval {require Mozilla::CA};for my$ca_bundle (qw{/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/ca-bundle.pem}){return$ca_bundle if -e $ca_bundle}die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/ .qq/Try installing Mozilla::CA from CPAN\n/}sub _ssl_args {my ($self,$host)=@_;my%ssl_args;if (Net::SSLeay::OPENSSL_VERSION_NUMBER()>= 0x01000000){$ssl_args{SSL_hostname}=$host,}if ($self->{verify_SSL}){$ssl_args{SSL_verifycn_scheme}='http';$ssl_args{SSL_verifycn_name}=$host;$ssl_args{SSL_verify_mode}=0x01;$ssl_args{SSL_ca_file}=$self->_find_CA_file}else {$ssl_args{SSL_verifycn_scheme}='none';$ssl_args{SSL_verify_mode}=0x00}for my$k (keys %{$self->{SSL_options}}){$ssl_args{$k}=$self->{SSL_options}{$k}if$k =~ m/^SSL_/}return \%ssl_args}1;
       sub $sub_name {
           my (\$self, \$url, \$args) = \@_;
           \@_ == 2 || (\@_ == 3 && ref \$args eq 'HASH')
@@ -253,8 +253,8 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   HERE
 HTTP_TINY
 
-$fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
-  package JSON::PP;use 5.005;use strict;use base qw(Exporter);use overload ();use Carp ();use B ();$JSON::PP::VERSION='2.27202';@JSON::PP::EXPORT=qw(encode_json decode_json from_json to_json);use constant P_ASCII=>0;use constant P_LATIN1=>1;use constant P_UTF8=>2;use constant P_INDENT=>3;use constant P_CANONICAL=>4;use constant P_SPACE_BEFORE=>5;use constant P_SPACE_AFTER=>6;use constant P_ALLOW_NONREF=>7;use constant P_SHRINK=>8;use constant P_ALLOW_BLESSED=>9;use constant P_CONVERT_BLESSED=>10;use constant P_RELAXED=>11;use constant P_LOOSE=>12;use constant P_ALLOW_BIGNUM=>13;use constant P_ALLOW_BAREKEY=>14;use constant P_ALLOW_SINGLEQUOTE=>15;use constant P_ESCAPE_SLASH=>16;use constant P_AS_NONBLESSED=>17;use constant P_ALLOW_UNKNOWN=>18;use constant OLD_PERL=>$] < 5.008 ? 1 : 0;BEGIN {my@xs_compati_bit_properties=qw(latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed convert_blessed relaxed allow_unknown);my@pp_bit_properties=qw(allow_singlequote allow_bignum loose allow_barekey escape_slash as_nonblessed);if ($] < 5.008){my$helper=$] >= 5.006 ? 'JSON::PP::Compat5006' : 'JSON::PP::Compat5005';eval qq| require $helper |;if ($@){Carp::croak $@}}for my$name (@xs_compati_bit_properties,@pp_bit_properties){my$flag_name='P_' .uc($name);eval qq/
+$fatpacked{"JSON/PP.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'JSON_PP';
+  package JSON::PP;use 5.005;use strict;use base qw(Exporter);use overload ();use Carp ();use B ();$JSON::PP::VERSION='2.27203';@JSON::PP::EXPORT=qw(encode_json decode_json from_json to_json);use constant P_ASCII=>0;use constant P_LATIN1=>1;use constant P_UTF8=>2;use constant P_INDENT=>3;use constant P_CANONICAL=>4;use constant P_SPACE_BEFORE=>5;use constant P_SPACE_AFTER=>6;use constant P_ALLOW_NONREF=>7;use constant P_SHRINK=>8;use constant P_ALLOW_BLESSED=>9;use constant P_CONVERT_BLESSED=>10;use constant P_RELAXED=>11;use constant P_LOOSE=>12;use constant P_ALLOW_BIGNUM=>13;use constant P_ALLOW_BAREKEY=>14;use constant P_ALLOW_SINGLEQUOTE=>15;use constant P_ESCAPE_SLASH=>16;use constant P_AS_NONBLESSED=>17;use constant P_ALLOW_UNKNOWN=>18;use constant OLD_PERL=>$] < 5.008 ? 1 : 0;BEGIN {my@xs_compati_bit_properties=qw(latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed convert_blessed relaxed allow_unknown);my@pp_bit_properties=qw(allow_singlequote allow_bignum loose allow_barekey escape_slash as_nonblessed);if ($] < 5.008){my$helper=$] >= 5.006 ? 'JSON::PP::Compat5006' : 'JSON::PP::Compat5005';eval qq| require $helper |;if ($@){Carp::croak $@}}for my$name (@xs_compati_bit_properties,@pp_bit_properties){my$flag_name='P_' .uc($name);eval qq/
               sub $name {
                   my \$enable = defined \$_[1] ? \$_[1] : 1;
   
@@ -298,18 +298,18 @@ $fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
               }
               $_[0]->{_incr_parser}->{incr_text};
           }
-      } if ($] >= 5.006)}BEGIN {eval 'require Scalar::Util';unless($@){*JSON::PP::blessed=\&Scalar::Util::blessed;*JSON::PP::reftype=\&Scalar::Util::reftype;*JSON::PP::refaddr=\&Scalar::Util::refaddr}else{eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }';*JSON::PP::blessed=sub {local($@,$SIG{__DIE__},$SIG{__WARN__});ref($_[0])? eval {$_[0]->a_sub_not_likely_to_be_here}: undef};my%tmap=qw(B::NULL SCALAR B::HV HASH B::AV ARRAY B::CV CODE B::IO IO B::GV GLOB B::REGEXP REGEXP);*JSON::PP::reftype=sub {my$r=shift;return undef unless length(ref($r));my$t=ref(B::svref_2object($r));return exists$tmap{$t}? $tmap{$t}: length(ref($$r))? 'REF' : 'SCALAR'};*JSON::PP::refaddr=sub {return undef unless length(ref($_[0]));my$addr;if(defined(my$pkg=blessed($_[0]))){$addr .= bless $_[0],'Scalar::Util::Fake';bless $_[0],$pkg}else {$addr .= $_[0]}$addr =~ /0x(\w+)/;local $^W;hex($1)}}}$JSON::PP::true=do {bless \(my$dummy=1),"JSON::PP::Boolean"};$JSON::PP::false=do {bless \(my$dummy=0),"JSON::PP::Boolean"};sub is_bool {defined $_[0]and UNIVERSAL::isa($_[0],"JSON::PP::Boolean")}sub true {$JSON::PP::true}sub false {$JSON::PP::false}sub null {undef}package JSON::PP::Boolean;use overload ("0+"=>sub {${$_[0]}},"++"=>sub {$_[0]=${$_[0]}+ 1},"--"=>sub {$_[0]=${$_[0]}- 1},fallback=>1,);package JSON::PP::IncrParser;use strict;use constant INCR_M_WS=>0;use constant INCR_M_STR=>1;use constant INCR_M_BS=>2;use constant INCR_M_JSON=>3;use constant INCR_M_C0=>4;use constant INCR_M_C1=>5;$JSON::PP::IncrParser::VERSION='1.01';my$unpack_format=$] < 5.006 ? 'C*' : 'U*';sub new {my ($class)=@_;bless {incr_nest=>0,incr_text=>undef,incr_parsing=>0,incr_p=>0,},$class}sub incr_parse {my ($self,$coder,$text)=@_;$self->{incr_text}='' unless (defined$self->{incr_text});if (defined$text){if (utf8::is_utf8($text)and!utf8::is_utf8($self->{incr_text})){utf8::upgrade($self->{incr_text});utf8::decode($self->{incr_text})}$self->{incr_text}.= $text}my$max_size=$coder->get_max_size;if (defined wantarray){$self->{incr_mode}=INCR_M_WS unless defined$self->{incr_mode};if (wantarray){my@ret;$self->{incr_parsing}=1;do {push@ret,$self->_incr_parse($coder,$self->{incr_text});unless (!$self->{incr_nest}and $self->{incr_mode}==INCR_M_JSON){$self->{incr_mode}=INCR_M_WS if$self->{incr_mode}!=INCR_M_STR}}until (length$self->{incr_text}>= $self->{incr_p});$self->{incr_parsing}=0;return@ret}else {$self->{incr_parsing}=1;my$obj=$self->_incr_parse($coder,$self->{incr_text});$self->{incr_parsing}=0 if defined$obj;return$obj ? $obj : undef}}}sub _incr_parse {my ($self,$coder,$text,$skip)=@_;my$p=$self->{incr_p};my$restore=$p;my@obj;my$len=length$text;if ($self->{incr_mode}==INCR_M_WS){while ($len > $p){my$s=substr($text,$p,1);$p++ and next if (0x20 >= unpack($unpack_format,$s));$self->{incr_mode}=INCR_M_JSON;last}}while ($len > $p){my$s=substr($text,$p++,1);if ($s eq '"'){if (substr($text,$p - 2,1)eq '\\'){next}if ($self->{incr_mode}!=INCR_M_STR){$self->{incr_mode}=INCR_M_STR}else {$self->{incr_mode}=INCR_M_JSON;unless ($self->{incr_nest}){last}}}if ($self->{incr_mode}==INCR_M_JSON){if ($s eq '[' or $s eq '{'){if (++$self->{incr_nest}> $coder->get_max_depth){Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')}}elsif ($s eq ']' or $s eq '}'){last if (--$self->{incr_nest}<= 0)}elsif ($s eq '#'){while ($len > $p){last if substr($text,$p++,1)eq "\n"}}}}$self->{incr_p}=$p;return if ($self->{incr_mode}==INCR_M_STR and not $self->{incr_nest});return if ($self->{incr_mode}==INCR_M_JSON and $self->{incr_nest}> 0);return '' unless (length substr($self->{incr_text},0,$p));local$Carp::CarpLevel=2;$self->{incr_p}=$restore;$self->{incr_c}=$p;my ($obj,$tail)=$coder->PP_decode_json(substr($self->{incr_text},0,$p),0x10000001);$self->{incr_text}=substr($self->{incr_text},$p);$self->{incr_p}=0;return$obj or ''}sub incr_text {if ($_[0]->{incr_parsing}){Carp::croak("incr_text can not be called when the incremental parser already started parsing")}$_[0]->{incr_text}}sub incr_skip {my$self=shift;$self->{incr_text}=substr($self->{incr_text},$self->{incr_c});$self->{incr_p}=0}sub incr_reset {my$self=shift;$self->{incr_text}=undef;$self->{incr_p}=0;$self->{incr_mode}=0;$self->{incr_nest}=0;$self->{incr_parsing}=0}1;
+      } if ($] >= 5.006)}BEGIN {eval 'require Scalar::Util';unless($@){*JSON::PP::blessed=\&Scalar::Util::blessed;*JSON::PP::reftype=\&Scalar::Util::reftype;*JSON::PP::refaddr=\&Scalar::Util::refaddr}else{eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }';*JSON::PP::blessed=sub {local($@,$SIG{__DIE__},$SIG{__WARN__});ref($_[0])? eval {$_[0]->a_sub_not_likely_to_be_here}: undef};my%tmap=qw(B::NULL SCALAR B::HV HASH B::AV ARRAY B::CV CODE B::IO IO B::GV GLOB B::REGEXP REGEXP);*JSON::PP::reftype=sub {my$r=shift;return undef unless length(ref($r));my$t=ref(B::svref_2object($r));return exists$tmap{$t}? $tmap{$t}: length(ref($$r))? 'REF' : 'SCALAR'};*JSON::PP::refaddr=sub {return undef unless length(ref($_[0]));my$addr;if(defined(my$pkg=blessed($_[0]))){$addr .= bless $_[0],'Scalar::Util::Fake';bless $_[0],$pkg}else {$addr .= $_[0]}$addr =~ /0x(\w+)/;local $^W;hex($1)}}}$JSON::PP::true=do {bless \(my$dummy=1),"JSON::PP::Boolean"};$JSON::PP::false=do {bless \(my$dummy=0),"JSON::PP::Boolean"};sub is_bool {defined $_[0]and UNIVERSAL::isa($_[0],"JSON::PP::Boolean")}sub true {$JSON::PP::true}sub false {$JSON::PP::false}sub null {undef}package JSON::PP::Boolean;use overload ("0+"=>sub {${$_[0]}},"++"=>sub {$_[0]=${$_[0]}+ 1},"--"=>sub {$_[0]=${$_[0]}- 1},fallback=>1,);package JSON::PP::IncrParser;use strict;use constant INCR_M_WS=>0;use constant INCR_M_STR=>1;use constant INCR_M_BS=>2;use constant INCR_M_JSON=>3;use constant INCR_M_C0=>4;use constant INCR_M_C1=>5;$JSON::PP::IncrParser::VERSION='1.01';my$unpack_format=$] < 5.006 ? 'C*' : 'U*';sub new {my ($class)=@_;bless {incr_nest=>0,incr_text=>undef,incr_parsing=>0,incr_p=>0,},$class}sub incr_parse {my ($self,$coder,$text)=@_;$self->{incr_text}='' unless (defined$self->{incr_text});if (defined$text){if (utf8::is_utf8($text)and!utf8::is_utf8($self->{incr_text})){utf8::upgrade($self->{incr_text});utf8::decode($self->{incr_text})}$self->{incr_text}.= $text}my$max_size=$coder->get_max_size;if (defined wantarray){$self->{incr_mode}=INCR_M_WS unless defined$self->{incr_mode};if (wantarray){my@ret;$self->{incr_parsing}=1;do {push@ret,$self->_incr_parse($coder,$self->{incr_text});unless (!$self->{incr_nest}and $self->{incr_mode}==INCR_M_JSON){$self->{incr_mode}=INCR_M_WS if$self->{incr_mode}!=INCR_M_STR}}until (length$self->{incr_text}>= $self->{incr_p});$self->{incr_parsing}=0;return@ret}else {$self->{incr_parsing}=1;my$obj=$self->_incr_parse($coder,$self->{incr_text});$self->{incr_parsing}=0 if defined$obj;return$obj ? $obj : undef}}}sub _incr_parse {my ($self,$coder,$text,$skip)=@_;my$p=$self->{incr_p};my$restore=$p;my@obj;my$len=length$text;if ($self->{incr_mode}==INCR_M_WS){while ($len > $p){my$s=substr($text,$p,1);$p++ and next if (0x20 >= unpack($unpack_format,$s));$self->{incr_mode}=INCR_M_JSON;last}}while ($len > $p){my$s=substr($text,$p++,1);if ($s eq '"'){if (substr($text,$p - 2,1)eq '\\'){next}if ($self->{incr_mode}!=INCR_M_STR){$self->{incr_mode}=INCR_M_STR}else {$self->{incr_mode}=INCR_M_JSON;unless ($self->{incr_nest}){last}}}if ($self->{incr_mode}==INCR_M_JSON){if ($s eq '[' or $s eq '{'){if (++$self->{incr_nest}> $coder->get_max_depth){Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')}}elsif ($s eq ']' or $s eq '}'){last if (--$self->{incr_nest}<= 0)}elsif ($s eq '#'){while ($len > $p){last if substr($text,$p++,1)eq "\n"}}}}$self->{incr_p}=$p;return if ($self->{incr_mode}==INCR_M_STR and not $self->{incr_nest});return if ($self->{incr_mode}==INCR_M_JSON and $self->{incr_nest}> 0);return '' unless (length substr($self->{incr_text},0,$p));local$Carp::CarpLevel=2;$self->{incr_p}=$restore;$self->{incr_c}=$p;my ($obj,$tail)=$coder->PP_decode_json(substr($self->{incr_text},0,$p),0x10000001);$self->{incr_text}=substr($self->{incr_text},$p);$self->{incr_p}=0;return$obj || ''}sub incr_text {if ($_[0]->{incr_parsing}){Carp::croak("incr_text can not be called when the incremental parser already started parsing")}$_[0]->{incr_text}}sub incr_skip {my$self=shift;$self->{incr_text}=substr($self->{incr_text},$self->{incr_c});$self->{incr_p}=0}sub incr_reset {my$self=shift;$self->{incr_text}=undef;$self->{incr_p}=0;$self->{incr_mode}=0;$self->{incr_nest}=0;$self->{incr_parsing}=0}1;
 JSON_PP
 
-$fatpacked{"JSON/PP/Boolean.pm"} = <<'JSON_PP_BOOLEAN';
+$fatpacked{"JSON/PP/Boolean.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'JSON_PP_BOOLEAN';
   use JSON::PP ();use strict;1;
 JSON_PP_BOOLEAN
 
-$fatpacked{"Module/CPANfile.pm"} = <<'MODULE_CPANFILE';
+$fatpacked{"Module/CPANfile.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE';
   package Module::CPANfile;use strict;use warnings;use Cwd;use Carp ();use Module::CPANfile::Environment;use Module::CPANfile::Result;our$VERSION='1.0002';sub new {my($class,$file)=@_;bless {},$class}sub load {my($proto,$file)=@_;my$self=ref$proto ? $proto : $proto->new;$self->parse($file || Cwd::abs_path('cpanfile'));$self}sub save {my($self,$path)=@_;open my$out,">",$path or die "$path: $!";print {$out}$self->to_string}sub parse {my($self,$file)=@_;my$code=do {open my$fh,"<",$file or die "$file: $!";join '',<$fh>};my$env=Module::CPANfile::Environment->new($file);$self->{result}=$env->parse($code)or die $@}sub from_prereqs {my($proto,$prereqs)=@_;my$self=$proto->new;$self->{result}=Module::CPANfile::Result->from_prereqs($prereqs);$self}sub features {my$self=shift;map$self->feature($_),keys %{$self->{result}{features}}}sub feature {my($self,$identifier)=@_;my$data=$self->{result}{features}{$identifier}or Carp::croak("Unknown feature '$identifier'");require CPAN::Meta::Feature;CPAN::Meta::Feature->new($data->{identifier},{description=>$data->{description},prereqs=>$data->{spec},})}sub prereq {shift->prereqs}sub prereqs {my$self=shift;require CPAN::Meta::Prereqs;CPAN::Meta::Prereqs->new($self->prereq_specs)}sub effective_prereqs {my($self,$features)=@_;$self->prereqs_with(@{$features || []})}sub prereqs_with {my($self,@feature_identifiers)=@_;my$prereqs=$self->prereqs;my@others=map {$self->feature($_)->prereqs}@feature_identifiers;$prereqs->with_merged_prereqs(\@others)}sub prereq_specs {my$self=shift;$self->{result}{spec}}sub merge_meta {my($self,$file,$version)=@_;require CPAN::Meta;$version ||=$file =~ /\.yml$/ ? '1.4' : '2';my$prereq=$self->prereqs;my$meta=CPAN::Meta->load_file($file);my$prereqs_hash=$prereq->with_merged_prereqs($meta->effective_prereqs)->as_string_hash;my$struct={%{$meta->as_struct},prereqs=>$prereqs_hash };CPAN::Meta->new($struct)->save($file,{version=>$version })}sub _dump {my$str=shift;require Data::Dumper;chomp(my$value=Data::Dumper->new([$str])->Terse(1)->Dump);$value}sub to_string {my($self,$include_empty)=@_;my$prereqs=$self->{result}{spec};my$code='';$code .= $self->_dump_prereqs($self->{result}{spec},$include_empty);for my$feature (values %{$self->{result}{features}}){$code .= sprintf "feature %s, %s => sub {\n",_dump($feature->{identifier}),_dump($feature->{description});$code .= $self->_dump_prereqs($feature->{spec},$include_empty,4);$code .= "}\n\n"}$code =~ s/\n+$/\n/s;$code}sub _dump_prereqs {my($self,$prereqs,$include_empty,$base_indent)=@_;my$code='';for my$phase (qw(runtime configure build test develop)){my$indent=$phase eq 'runtime' ? '' : '    ';$indent=(' ' x ($base_indent || 0)).$indent;my($phase_code,$requirements);$phase_code .= "on $phase => sub {\n" unless$phase eq 'runtime';for my$type (qw(requires recommends suggests conflicts)){for my$mod (sort keys %{$prereqs->{$phase}{$type}}){my$ver=$prereqs->{$phase}{$type}{$mod};$phase_code .= $ver eq '0' ? "${indent}$type '$mod';\n" : "${indent}$type '$mod', '$ver';\n";$requirements++}}$phase_code .= "\n" unless$requirements;$phase_code .= "};\n" unless$phase eq 'runtime';$code .= $phase_code ."\n" if$requirements or $include_empty}$code =~ s/\n+$/\n/s;$code}1;
 MODULE_CPANFILE
 
-$fatpacked{"Module/CPANfile/Environment.pm"} = <<'MODULE_CPANFILE_ENVIRONMENT';
+$fatpacked{"Module/CPANfile/Environment.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE_ENVIRONMENT';
   package Module::CPANfile::Environment;use strict;use warnings;use Module::CPANfile::Result;use Carp ();my@bindings=qw(on requires recommends suggests conflicts feature osname configure_requires build_requires test_requires author_requires);my$file_id=1;sub new {my($class,$file)=@_;bless {file=>$file,},$class}sub bind {my$class=shift;my$pkg=caller;my$result=Module::CPANfile::Result->new;for my$binding (@bindings){no strict 'refs';*{"$pkg\::$binding"}=sub {$result->$binding(@_)}}return$result}sub parse {my($self,$code)=@_;my($res,$err);{local $@;$file_id++;$res=eval <<EVAL;$err=$@}if ($err){die "Parsing $self->{file} failed: $err"};return$res}1;
   package Module::CPANfile::Sandbox$file_id;
   no warnings;
@@ -323,12 +323,12 @@ $fatpacked{"Module/CPANfile/Environment.pm"} = <<'MODULE_CPANFILE_ENVIRONMENT';
   EVAL
 MODULE_CPANFILE_ENVIRONMENT
 
-$fatpacked{"Module/CPANfile/Result.pm"} = <<'MODULE_CPANFILE_RESULT';
+$fatpacked{"Module/CPANfile/Result.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE_RESULT';
   package Module::CPANfile::Result;use strict;sub from_prereqs {my($class,$spec)=@_;bless {phase=>'runtime',spec=>$spec,},$class}sub new {bless {phase=>'runtime',features=>{},feature=>undef,spec=>{},},shift}sub on {my($self,$phase,$code)=@_;local$self->{phase}=$phase;$code->()}sub feature {my($self,$identifier,$description,$code)=@_;if (@_==3 && ref($description)eq 'CODE'){$code=$description;$description=$identifier}unless (ref$description eq '' && ref$code eq 'CODE'){Carp::croak("Usage: feature 'identifier', 'Description' => sub { ... }")}local$self->{feature}=$self->{features}{$identifier}={identifier=>$identifier,description=>$description,spec=>{}};$code->()}sub osname {die "TODO"}sub requires {my($self,$module,$requirement)=@_;($self->{feature}? $self->{feature}{spec}: $self->{spec})->{$self->{phase}}{requires}{$module}=$requirement || 0}sub recommends {my($self,$module,$requirement)=@_;($self->{feature}? $self->{feature}{spec}: $self->{spec})->{$self->{phase}}{recommends}{$module}=$requirement || 0}sub suggests {my($self,$module,$requirement)=@_;($self->{feature}? $self->{feature}{spec}: $self->{spec})->{$self->{phase}}{suggests}{$module}=$requirement || 0}sub conflicts {my($self,$module,$requirement)=@_;($self->{feature}? $self->{feature}{spec}: $self->{spec})->{$self->{phase}}{conflicts}{$module}=$requirement || 0}sub configure_requires {my($self,@args)=@_;$self->on(configure=>sub {$self->requires(@args)})}sub build_requires {my($self,@args)=@_;$self->on(build=>sub {$self->requires(@args)})}sub test_requires {my($self,@args)=@_;$self->on(test=>sub {$self->requires(@args)})}sub author_requires {my($self,@args)=@_;$self->on(develop=>sub {$self->requires(@args)})}1;
 MODULE_CPANFILE_RESULT
 
-$fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
-  package Module::Metadata;use strict;use vars qw($VERSION);$VERSION='1.000016';$VERSION=eval$VERSION;use Carp qw/croak/;use File::Spec;use IO::File;use version 0.87;BEGIN {if ($INC{'Log/Contextual.pm'}){Log::Contextual->import('log_info')}else {*log_info=sub (&) {warn $_[0]->()}}}use File::Find qw(find);my$V_NUM_REGEXP=qr{v?[0-9._]+};my$PKG_FIRST_WORD_REGEXP=qr{ # the FIRST word in a package name
+$fatpacked{"Module/Metadata.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_METADATA';
+  package Module::Metadata;use strict;use warnings;our$VERSION='1.000019';$VERSION=eval$VERSION;use Carp qw/croak/;use File::Spec;use IO::File;use version 0.87;BEGIN {if ($INC{'Log/Contextual.pm'}){Log::Contextual->import('log_info')}else {*log_info=sub (&) {warn $_[0]->()}}}use File::Find qw(find);my$V_NUM_REGEXP=qr{v?[0-9._]+};my$PKG_FIRST_WORD_REGEXP=qr{ # the FIRST word in a package name
     [a-zA-Z_]                     # the first word CANNOT start with a digit
       (?:
         [\w']?                    # can contain letters, digits, _, or ticks
@@ -363,7 +363,7 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
     ([\$*])         # sigil - $ or *
     (
       (             # optional leading package name
-        (?:::|\')?  # possibly starting like just :: (Ì  la $::VERSION)
+        (?:::|\')?  # possibly starting like just :: (a la $::VERSION)
         (?:\w+(?:::|\'))*  # Foo::Bar:: ...
       )?
       VERSION
@@ -376,10 +376,11 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
     )
     \s*
     =[^=~]  # = but not ==, nor =~
-  }x;sub new_from_file {my$class=shift;my$filename=File::Spec->rel2abs(shift);return undef unless defined($filename)&& -f $filename;return$class->_init(undef,$filename,@_)}sub new_from_handle {my$class=shift;my$handle=shift;my$filename=shift;return undef unless defined($handle)&& defined($filename);$filename=File::Spec->rel2abs($filename);return$class->_init(undef,$filename,@_,handle=>$handle)}sub new_from_module {my$class=shift;my$module=shift;my%props=@_;$props{inc}||=\@INC;my$filename=$class->find_module_by_name($module,$props{inc});return undef unless defined($filename)&& -f $filename;return$class->_init($module,$filename,%props)}{my$compare_versions=sub {my ($v1,$op,$v2)=@_;$v1=version->new($v1)unless UNIVERSAL::isa($v1,'version');my$eval_str="\$v1 $op \$v2";my$result=eval$eval_str;log_info {"error comparing versions: '$eval_str' $@"}if $@;return$result};my$normalize_version=sub {my ($version)=@_;if ($version =~ /[=<>!,]/){}elsif (ref$version eq 'version'){$version=$version->is_qv ? $version->normal : $version->stringify}elsif ($version =~ /^[^v][^.]*\.[^.]+\./){$version="v$version"}else {}return$version};my$resolve_module_versions=sub {my$packages=shift;my($file,$version);my$err='';for my$p (@$packages){if (defined($p->{version})){if (defined($version)){if ($compare_versions->($version,'!=',$p->{version})){$err .= "  $p->{file} ($p->{version})\n"}else {}}else {$file=$p->{file};$version=$p->{version}}}$file ||=$p->{file}if defined($p->{file})}if ($err){$err="  $file ($version)\n" .$err}my%result=(file=>$file,version=>$version,err=>$err);return \%result};sub provides {my$class=shift;croak "provides() requires key/value pairs \n" if @_ % 2;my%args=@_;croak "provides() takes only one of 'dir' or 'files'\n" if$args{dir}&& $args{files};croak "provides() requires a 'version' argument" unless defined$args{version};croak "provides() does not support version '$args{version}' metadata" unless grep {$args{version}eq $_}qw/1.4 2/;$args{prefix}='lib' unless defined$args{prefix};my$p;if ($args{dir}){$p=$class->package_versions_from_directory($args{dir})}else {croak "provides() requires 'files' to be an array reference\n" unless ref$args{files}eq 'ARRAY';$p=$class->package_versions_from_directory($args{files})}if (length$args{prefix}){$args{prefix}=~ s{/$}{};for my$v (values %$p){$v->{file}="$args{prefix}/$v->{file}"}}return$p}sub package_versions_from_directory {my ($class,$dir,$files)=@_;my@files;if ($files){@files=@$files}else {find({wanted=>sub {push@files,$_ if -f $_ && /\.pm$/},no_chdir=>1,},$dir)}my(%prime,%alt);for my$file (@files){my$mapped_filename=File::Spec::Unix->abs2rel($file,$dir);my@path=split(/\//,$mapped_filename);(my$prime_package=join('::',@path))=~ s/\.pm$//;my$pm_info=$class->new_from_file($file);for my$package ($pm_info->packages_inside){next if$package eq 'main';next if$package eq 'DB';next if grep /^_/,split(/::/,$package);my$version=$pm_info->version($package);$prime_package=$package if lc($prime_package)eq lc($package);if ($package eq $prime_package){if (exists($prime{$package})){croak "Unexpected conflict in '$package'; multiple versions found.\n"}else {$mapped_filename="$package.pm" if lc("$package.pm")eq lc($mapped_filename);$prime{$package}{file}=$mapped_filename;$prime{$package}{version}=$version if defined($version)}}else {push(@{$alt{$package}},{file=>$mapped_filename,version=>$version,})}}}for my$package (keys(%alt)){my$result=$resolve_module_versions->($alt{$package});if (exists($prime{$package})){if ($result->{err}){log_info {"Found conflicting versions for package '$package'\n" ."  $prime{$package}{file} ($prime{$package}{version})\n" .$result->{err}}}elsif (defined($result->{version})){if (exists($prime{$package}{version})&& defined($prime{$package}{version})){if ($compare_versions->($prime{$package}{version},'!=',$result->{version})){log_info {"Found conflicting versions for package '$package'\n" ."  $prime{$package}{file} ($prime{$package}{version})\n" ."  $result->{file} ($result->{version})\n"}}}else {$prime{$package}{file}=$result->{file};$prime{$package}{version}=$result->{version}}}else {}}else {if ($result->{err}){log_info {"Found conflicting versions for package '$package'\n" .$result->{err}}}$prime{$package}{file}=$result->{file};$prime{$package}{version}=$result->{version}if defined($result->{version})}}for (grep defined $_->{version},values%prime){$_->{version}=$normalize_version->($_->{version})}return \%prime}}sub _init {my$class=shift;my$module=shift;my$filename=shift;my%props=@_;my$handle=delete$props{handle};my(%valid_props,@valid_props);@valid_props=qw(collect_pod inc);@valid_props{@valid_props}=delete(@props{@valid_props});warn "Unknown properties: @{[keys %props]}\n" if scalar(%props);my%data=(module=>$module,filename=>$filename,version=>undef,packages=>[],versions=>{},pod=>{},pod_headings=>[],collect_pod=>0,%valid_props,);my$self=bless(\%data,$class);if ($handle){$self->_parse_fh($handle)}else {$self->_parse_file()}unless($self->{module}and length($self->{module})){my ($v,$d,$f)=File::Spec->splitpath($self->{filename});if($f =~ /\.pm$/){$f =~ s/\..+$//;my@candidates=grep /$f$/,@{$self->{packages}};$self->{module}=shift(@candidates)}else {if(grep /main/,@{$self->{packages}}){$self->{module}='main'}else {$self->{module}=$self->{packages}[0]|| ''}}}$self->{version}=$self->{versions}{$self->{module}}if defined($self->{module});return$self}sub _do_find_module {my$class=shift;my$module=shift || croak 'find_module_by_name() requires a package name';my$dirs=shift || \@INC;my$file=File::Spec->catfile(split(/::/,$module));for my$dir (@$dirs){my$testfile=File::Spec->catfile($dir,$file);return [File::Spec->rel2abs($testfile),$dir ]if -e $testfile and!-d _;return [File::Spec->rel2abs("$testfile.pm"),$dir ]if -e "$testfile.pm"}return}sub find_module_by_name {my$found=shift()->_do_find_module(@_)or return;return$found->[0]}sub find_module_dir_by_name {my$found=shift()->_do_find_module(@_)or return;return$found->[1]}sub _parse_version_expression {my$self=shift;my$line=shift;my($sig,$var,$pkg);if ($line =~ /$VERS_REGEXP/o){($sig,$var,$pkg)=$2 ? ($1,$2,$3): ($4,$5,$6);if ($pkg){$pkg=($pkg eq '::')? 'main' : $pkg;$pkg =~ s/::$//}}return ($sig,$var,$pkg)}sub _parse_file {my$self=shift;my$filename=$self->{filename};my$fh=IO::File->new($filename)or croak("Can't open '$filename': $!");$self->_handle_bom($fh,$filename);$self->_parse_fh($fh)}sub _handle_bom {my ($self,$fh,$filename)=@_;my$pos=$fh->getpos;return unless defined$pos;my$buf=' ' x 2;my$count=$fh->read($buf,length$buf);return unless defined$count and $count >= 2;my$encoding;if ($buf eq "\x{FE}\x{FF}"){$encoding='UTF-16BE'}elsif ($buf eq "\x{FF}\x{FE}"){$encoding='UTF-16LE'}elsif ($buf eq "\x{EF}\x{BB}"){$buf=' ';$count=$fh->read($buf,length$buf);if (defined$count and $count >= 1 and $buf eq "\x{BF}"){$encoding='UTF-8'}}if (defined$encoding){if ("$]" >= 5.008){binmode($fh,":encoding($encoding)")}}else {$fh->setpos($pos)or croak(sprintf "Can't reset position to the top of '$filename'")}return$encoding}sub _parse_fh {my ($self,$fh)=@_;my($in_pod,$seen_end,$need_vers)=(0,0,0);my(@pkgs,%vers,%pod,@pod);my$pkg='main';my$pod_sect='';my$pod_data='';my$in_end=0;while (defined(my$line=<$fh>)){my$line_num=$.;chomp($line);my$is_cut;if ($line =~ /^=([a-zA-Z].*)/){my$cmd=$1;$is_cut=$cmd =~ /^cut(?:[^a-zA-Z]|$)/;$in_pod=!$is_cut}if ($in_pod){if ($line =~ /^=head[1-4]\s+(.+)\s*$/){push(@pod,$1);if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data;$pod_data=''}$pod_sect=$1}elsif ($self->{collect_pod}){$pod_data .= "$line\n"}}elsif ($is_cut){if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data;$pod_data=''}$pod_sect=''}else {next if$in_end;next if$line =~ /^\s*#/;if ($line eq '__END__'){$in_end++;next}last if$line eq '__DATA__';my($vers_sig,$vers_fullname,$vers_pkg)=($line =~ /VERSION/)? $self->_parse_version_expression($line): ();if ($line =~ /$PKG_REGEXP/o){$pkg=$1;push(@pkgs,$pkg)unless grep($pkg eq $_,@pkgs);$vers{$pkg}=$2 unless exists($vers{$pkg});$need_vers=defined $2 ? 0 : 1}elsif ($vers_fullname && $vers_pkg){push(@pkgs,$vers_pkg)unless grep($vers_pkg eq $_,@pkgs);$need_vers=0 if$vers_pkg eq $pkg;unless (defined$vers{$vers_pkg}&& length$vers{$vers_pkg}){$vers{$vers_pkg}=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line)}}elsif (!exists($vers{main})&& $pkg eq 'main' && $vers_fullname){$need_vers=0;my$v=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line);$vers{$pkg}=$v;push(@pkgs,'main')}elsif (!exists($vers{main})&& $pkg eq 'main' && $line =~ /\w+/){$need_vers=1;$vers{main}='';push(@pkgs,'main')}elsif ($vers_fullname && $need_vers){$need_vers=0;my$v=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line);unless (defined$vers{$pkg}&& length$vers{$pkg}){$vers{$pkg}=$v}}}}if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data}$self->{versions}=\%vers;$self->{packages}=\@pkgs;$self->{pod}=\%pod;$self->{pod_headings}=\@pod}{my$pn=0;sub _evaluate_version_line {my$self=shift;my($sigil,$var,$line)=@_;my$vsub;$pn++;my$eval=qq{BEGIN { q#  Hide from _packages_inside()
+  }x;sub new_from_file {my$class=shift;my$filename=File::Spec->rel2abs(shift);return undef unless defined($filename)&& -f $filename;return$class->_init(undef,$filename,@_)}sub new_from_handle {my$class=shift;my$handle=shift;my$filename=shift;return undef unless defined($handle)&& defined($filename);$filename=File::Spec->rel2abs($filename);return$class->_init(undef,$filename,@_,handle=>$handle)}sub new_from_module {my$class=shift;my$module=shift;my%props=@_;$props{inc}||=\@INC;my$filename=$class->find_module_by_name($module,$props{inc});return undef unless defined($filename)&& -f $filename;return$class->_init($module,$filename,%props)}{my$compare_versions=sub {my ($v1,$op,$v2)=@_;$v1=version->new($v1)unless UNIVERSAL::isa($v1,'version');my$eval_str="\$v1 $op \$v2";my$result=eval$eval_str;log_info {"error comparing versions: '$eval_str' $@"}if $@;return$result};my$normalize_version=sub {my ($version)=@_;if ($version =~ /[=<>!,]/){}elsif (ref$version eq 'version'){$version=$version->is_qv ? $version->normal : $version->stringify}elsif ($version =~ /^[^v][^.]*\.[^.]+\./){$version="v$version"}else {}return$version};my$resolve_module_versions=sub {my$packages=shift;my($file,$version);my$err='';for my$p (@$packages){if (defined($p->{version})){if (defined($version)){if ($compare_versions->($version,'!=',$p->{version})){$err .= "  $p->{file} ($p->{version})\n"}else {}}else {$file=$p->{file};$version=$p->{version}}}$file ||=$p->{file}if defined($p->{file})}if ($err){$err="  $file ($version)\n" .$err}my%result=(file=>$file,version=>$version,err=>$err);return \%result};sub provides {my$class=shift;croak "provides() requires key/value pairs \n" if @_ % 2;my%args=@_;croak "provides() takes only one of 'dir' or 'files'\n" if$args{dir}&& $args{files};croak "provides() requires a 'version' argument" unless defined$args{version};croak "provides() does not support version '$args{version}' metadata" unless grep {$args{version}eq $_}qw/1.4 2/;$args{prefix}='lib' unless defined$args{prefix};my$p;if ($args{dir}){$p=$class->package_versions_from_directory($args{dir})}else {croak "provides() requires 'files' to be an array reference\n" unless ref$args{files}eq 'ARRAY';$p=$class->package_versions_from_directory($args{files})}if (length$args{prefix}){$args{prefix}=~ s{/$}{};for my$v (values %$p){$v->{file}="$args{prefix}/$v->{file}"}}return$p}sub package_versions_from_directory {my ($class,$dir,$files)=@_;my@files;if ($files){@files=@$files}else {find({wanted=>sub {push@files,$_ if -f $_ && /\.pm$/},no_chdir=>1,},$dir)}my(%prime,%alt);for my$file (@files){my$mapped_filename=File::Spec::Unix->abs2rel($file,$dir);my@path=split(/\//,$mapped_filename);(my$prime_package=join('::',@path))=~ s/\.pm$//;my$pm_info=$class->new_from_file($file);for my$package ($pm_info->packages_inside){next if$package eq 'main';next if$package eq 'DB';next if grep /^_/,split(/::/,$package);my$version=$pm_info->version($package);$prime_package=$package if lc($prime_package)eq lc($package);if ($package eq $prime_package){if (exists($prime{$package})){croak "Unexpected conflict in '$package'; multiple versions found.\n"}else {$mapped_filename="$package.pm" if lc("$package.pm")eq lc($mapped_filename);$prime{$package}{file}=$mapped_filename;$prime{$package}{version}=$version if defined($version)}}else {push(@{$alt{$package}},{file=>$mapped_filename,version=>$version,})}}}for my$package (keys(%alt)){my$result=$resolve_module_versions->($alt{$package});if (exists($prime{$package})){if ($result->{err}){log_info {"Found conflicting versions for package '$package'\n" ."  $prime{$package}{file} ($prime{$package}{version})\n" .$result->{err}}}elsif (defined($result->{version})){if (exists($prime{$package}{version})&& defined($prime{$package}{version})){if ($compare_versions->($prime{$package}{version},'!=',$result->{version})){log_info {"Found conflicting versions for package '$package'\n" ."  $prime{$package}{file} ($prime{$package}{version})\n" ."  $result->{file} ($result->{version})\n"}}}else {$prime{$package}{file}=$result->{file};$prime{$package}{version}=$result->{version}}}else {}}else {if ($result->{err}){log_info {"Found conflicting versions for package '$package'\n" .$result->{err}}}$prime{$package}{file}=$result->{file};$prime{$package}{version}=$result->{version}if defined($result->{version})}}for (grep defined $_->{version},values%prime){$_->{version}=$normalize_version->($_->{version})}return \%prime}}sub _init {my$class=shift;my$module=shift;my$filename=shift;my%props=@_;my$handle=delete$props{handle};my(%valid_props,@valid_props);@valid_props=qw(collect_pod inc);@valid_props{@valid_props}=delete(@props{@valid_props});warn "Unknown properties: @{[keys %props]}\n" if scalar(%props);my%data=(module=>$module,filename=>$filename,version=>undef,packages=>[],versions=>{},pod=>{},pod_headings=>[],collect_pod=>0,%valid_props,);my$self=bless(\%data,$class);if ($handle){$self->_parse_fh($handle)}else {$self->_parse_file()}unless($self->{module}and length($self->{module})){my ($v,$d,$f)=File::Spec->splitpath($self->{filename});if($f =~ /\.pm$/){$f =~ s/\..+$//;my@candidates=grep /$f$/,@{$self->{packages}};$self->{module}=shift(@candidates)}else {if(grep /main/,@{$self->{packages}}){$self->{module}='main'}else {$self->{module}=$self->{packages}[0]|| ''}}}$self->{version}=$self->{versions}{$self->{module}}if defined($self->{module});return$self}sub _do_find_module {my$class=shift;my$module=shift || croak 'find_module_by_name() requires a package name';my$dirs=shift || \@INC;my$file=File::Spec->catfile(split(/::/,$module));for my$dir (@$dirs){my$testfile=File::Spec->catfile($dir,$file);return [File::Spec->rel2abs($testfile),$dir ]if -e $testfile and!-d _;return [File::Spec->rel2abs("$testfile.pm"),$dir ]if -e "$testfile.pm"}return}sub find_module_by_name {my$found=shift()->_do_find_module(@_)or return;return$found->[0]}sub find_module_dir_by_name {my$found=shift()->_do_find_module(@_)or return;return$found->[1]}sub _parse_version_expression {my$self=shift;my$line=shift;my($sig,$var,$pkg);if ($line =~ /$VERS_REGEXP/o){($sig,$var,$pkg)=$2 ? ($1,$2,$3): ($4,$5,$6);if ($pkg){$pkg=($pkg eq '::')? 'main' : $pkg;$pkg =~ s/::$//}}return ($sig,$var,$pkg)}sub _parse_file {my$self=shift;my$filename=$self->{filename};my$fh=IO::File->new($filename)or croak("Can't open '$filename': $!");$self->_handle_bom($fh,$filename);$self->_parse_fh($fh)}sub _handle_bom {my ($self,$fh,$filename)=@_;my$pos=$fh->getpos;return unless defined$pos;my$buf=' ' x 2;my$count=$fh->read($buf,length$buf);return unless defined$count and $count >= 2;my$encoding;if ($buf eq "\x{FE}\x{FF}"){$encoding='UTF-16BE'}elsif ($buf eq "\x{FF}\x{FE}"){$encoding='UTF-16LE'}elsif ($buf eq "\x{EF}\x{BB}"){$buf=' ';$count=$fh->read($buf,length$buf);if (defined$count and $count >= 1 and $buf eq "\x{BF}"){$encoding='UTF-8'}}if (defined$encoding){if ("$]" >= 5.008){binmode($fh,":encoding($encoding)")}}else {$fh->setpos($pos)or croak(sprintf "Can't reset position to the top of '$filename'")}return$encoding}sub _parse_fh {my ($self,$fh)=@_;my($in_pod,$seen_end,$need_vers)=(0,0,0);my(@pkgs,%vers,%pod,@pod);my$pkg='main';my$pod_sect='';my$pod_data='';my$in_end=0;while (defined(my$line=<$fh>)){my$line_num=$.;chomp($line);my$is_cut;if ($line =~ /^=([a-zA-Z].*)/){my$cmd=$1;$is_cut=$cmd =~ /^cut(?:[^a-zA-Z]|$)/;$in_pod=!$is_cut}if ($in_pod){if ($line =~ /^=head[1-4]\s+(.+)\s*$/){push(@pod,$1);if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data;$pod_data=''}$pod_sect=$1}elsif ($self->{collect_pod}){$pod_data .= "$line\n"}}elsif ($is_cut){if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data;$pod_data=''}$pod_sect=''}else {next if$in_end;next if$line =~ /^\s*#/;if ($line eq '__END__'){$in_end++;next}last if$line eq '__DATA__';my($vers_sig,$vers_fullname,$vers_pkg)=($line =~ /VERSION/)? $self->_parse_version_expression($line): ();if ($line =~ /$PKG_REGEXP/o){$pkg=$1;push(@pkgs,$pkg)unless grep($pkg eq $_,@pkgs);$vers{$pkg}=$2 unless exists($vers{$pkg});$need_vers=defined $2 ? 0 : 1}elsif ($vers_fullname && $vers_pkg){push(@pkgs,$vers_pkg)unless grep($vers_pkg eq $_,@pkgs);$need_vers=0 if$vers_pkg eq $pkg;unless (defined$vers{$vers_pkg}&& length$vers{$vers_pkg}){$vers{$vers_pkg}=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line)}}elsif (!exists($vers{main})&& $pkg eq 'main' && $vers_fullname){$need_vers=0;my$v=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line);$vers{$pkg}=$v;push(@pkgs,'main')}elsif (!exists($vers{main})&& $pkg eq 'main' && $line =~ /\w+/){$need_vers=1;$vers{main}='';push(@pkgs,'main')}elsif ($vers_fullname && $need_vers){$need_vers=0;my$v=$self->_evaluate_version_line($vers_sig,$vers_fullname,$line);unless (defined$vers{$pkg}&& length$vers{$pkg}){$vers{$pkg}=$v}}}}if ($self->{collect_pod}&& length($pod_data)){$pod{$pod_sect}=$pod_data}$self->{versions}=\%vers;$self->{packages}=\@pkgs;$self->{pod}=\%pod;$self->{pod_headings}=\@pod}{my$pn=0;sub _evaluate_version_line {my$self=shift;my($sigil,$var,$line)=@_;my$vsub;$pn++;my$eval=qq{BEGIN { my \$dummy = q#  Hide from _packages_inside()
       #; package Module::Metadata::_version::p$pn;
       use version;
       no strict;
+      no warnings;
   
         \$vsub = sub {
           local $sigil$var;
@@ -387,27 +388,27 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
           $line;
           \$$var
         };
-    }};local $^W;eval$eval;if ($@ =~ /Can't locate/ && -d 'lib'){local@INC=('lib',@INC);eval$eval}warn "Error evaling version line '$eval' in $self->{filename}: $@\n" if $@;(ref($vsub)eq 'CODE')or croak "failed to build version sub for $self->{filename}";my$result=eval {$vsub->()};croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" if $@;my$version=eval {_dwim_version($result)};croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n" unless defined$version;return$version}}{my@version_prep=(sub {return shift},sub {my$v=shift;$v =~ s{([0-9])[a-z-].*$}{$1}i;return$v},sub {my$v=shift;my$num_dots=()=$v =~ m{(\.)}g;my$num_unders=()=$v =~ m{(_)}g;my$leading_v=substr($v,0,1)eq 'v';if (!$leading_v && $num_dots < 2 && $num_unders > 1){$v =~ s{_}{}g;$num_unders=()=$v =~ m{(_)}g}return$v},sub {my$v=shift;no warnings 'numeric';return 0 + $v},);sub _dwim_version {my ($result)=shift;return$result if ref($result)eq 'version';my ($version,$error);for my$f (@version_prep){$result=$f->($result);$version=eval {version->new($result)};$error ||=$@ if $@;last if defined$version}croak$error unless defined$version;return$version}}sub name {$_[0]->{module}}sub filename {$_[0]->{filename}}sub packages_inside {@{$_[0]->{packages}}}sub pod_inside {@{$_[0]->{pod_headings}}}sub contains_pod {0+@{$_[0]->{pod_headings}}}sub version {my$self=shift;my$mod=shift || $self->{module};my$vers;if (defined($mod)&& length($mod)&& exists($self->{versions}{$mod})){return$self->{versions}{$mod}}else {return undef}}sub pod {my$self=shift;my$sect=shift;if (defined($sect)&& length($sect)&& exists($self->{pod}{$sect})){return$self->{pod}{$sect}}else {return undef}}1;
+    }};$eval=$1 if$eval =~ m{^(.+)}s;local $^W;eval$eval;if ($@ =~ /Can't locate/ && -d 'lib'){local@INC=('lib',@INC);eval$eval}warn "Error evaling version line '$eval' in $self->{filename}: $@\n" if $@;(ref($vsub)eq 'CODE')or croak "failed to build version sub for $self->{filename}";my$result=eval {$vsub->()};croak "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" if $@;my$version=eval {_dwim_version($result)};croak "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n" unless defined$version;return$version}}{my@version_prep=(sub {return shift},sub {my$v=shift;$v =~ s{([0-9])[a-z-].*$}{$1}i;return$v},sub {my$v=shift;my$num_dots=()=$v =~ m{(\.)}g;my$num_unders=()=$v =~ m{(_)}g;my$leading_v=substr($v,0,1)eq 'v';if (!$leading_v && $num_dots < 2 && $num_unders > 1){$v =~ s{_}{}g;$num_unders=()=$v =~ m{(_)}g}return$v},sub {my$v=shift;no warnings 'numeric';return 0 + $v},);sub _dwim_version {my ($result)=shift;return$result if ref($result)eq 'version';my ($version,$error);for my$f (@version_prep){$result=$f->($result);$version=eval {version->new($result)};$error ||=$@ if $@;last if defined$version}croak$error unless defined$version;return$version}}sub name {$_[0]->{module}}sub filename {$_[0]->{filename}}sub packages_inside {@{$_[0]->{packages}}}sub pod_inside {@{$_[0]->{pod_headings}}}sub contains_pod {0+@{$_[0]->{pod_headings}}}sub version {my$self=shift;my$mod=shift || $self->{module};my$vers;if (defined($mod)&& length($mod)&& exists($self->{versions}{$mod})){return$self->{versions}{$mod}}else {return undef}}sub pod {my$self=shift;my$sect=shift;if (defined($sect)&& length($sect)&& exists($self->{pod}{$sect})){return$self->{pod}{$sect}}else {return undef}}1;
 MODULE_METADATA
 
-$fatpacked{"Parse/CPAN/Meta.pm"} = <<'PARSE_CPAN_META';
+$fatpacked{"Parse/CPAN/Meta.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PARSE_CPAN_META';
   use strict;package Parse::CPAN::Meta;our$VERSION='1.4407';use Carp 'croak';sub HAVE_UTF8 () {$] >= 5.007003}sub IO_LAYER () {$] >= 5.008001 ? ":utf8" : ""}BEGIN {if (HAVE_UTF8){eval "require utf8;";die "Failed to load UTF-8 support" if $@}require 5.004;require Exporter;@Parse::CPAN::Meta::ISA=qw{Exporter};@Parse::CPAN::Meta::EXPORT_OK=qw{Load LoadFile}}sub load_file {my ($class,$filename)=@_;if ($filename =~ /\.ya?ml$/){return$class->load_yaml_string(_slurp($filename))}if ($filename =~ /\.json$/){return$class->load_json_string(_slurp($filename))}croak("file type cannot be determined by filename")}sub load_yaml_string {my ($class,$string)=@_;my$backend=$class->yaml_backend();my$data=eval {no strict 'refs';&{"$backend\::Load"}($string)};if ($@){croak$backend->can('errstr')? $backend->errstr : $@}return$data || {}}sub load_json_string {my ($class,$string)=@_;return$class->json_backend()->new->decode($string)}sub yaml_backend {local$Module::Load::Conditional::CHECK_INC_HASH=1;if (!defined$ENV{PERL_YAML_BACKEND}){_can_load('CPAN::Meta::YAML',0.002)or croak "CPAN::Meta::YAML 0.002 is not available\n";return "CPAN::Meta::YAML"}else {my$backend=$ENV{PERL_YAML_BACKEND};_can_load($backend)or croak "Could not load PERL_YAML_BACKEND '$backend'\n";$backend->can("Load")or croak "PERL_YAML_BACKEND '$backend' does not implement Load()\n";return$backend}}sub json_backend {local$Module::Load::Conditional::CHECK_INC_HASH=1;if (!$ENV{PERL_JSON_BACKEND}or $ENV{PERL_JSON_BACKEND}eq 'JSON::PP'){_can_load('JSON::PP'=>2.27103)or croak "JSON::PP 2.27103 is not available\n";return 'JSON::PP'}else {_can_load('JSON'=>2.5)or croak "JSON 2.5 is required for " ."\$ENV{PERL_JSON_BACKEND} = '$ENV{PERL_JSON_BACKEND}'\n";return "JSON"}}sub _slurp {open my$fh,"<" .IO_LAYER,"$_[0]" or die "can't open $_[0] for reading: $!";return do {local $/;<$fh>}}sub _can_load {my ($module,$version)=@_;(my$file=$module)=~ s{::}{/}g;$file .= ".pm";return 1 if$INC{$file};return 0 if exists$INC{$file};eval {require$file;1}or return 0;if (defined$version){eval {$module->VERSION($version);1}or return 0}return 1}sub LoadFile ($) {require CPAN::Meta::YAML;my$object=CPAN::Meta::YAML::LoadFile(shift)or die CPAN::Meta::YAML->errstr;return$object}sub Load ($) {require CPAN::Meta::YAML;my$object=CPAN::Meta::YAML::Load(shift)or die CPAN::Meta::YAML->errstr;return$object}1;
 PARSE_CPAN_META
 
-$fatpacked{"String/ShellQuote.pm"} = <<'STRING_SHELLQUOTE';
+$fatpacked{"String/ShellQuote.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'STRING_SHELLQUOTE';
   package String::ShellQuote;use strict;use vars qw($VERSION @ISA @EXPORT);require Exporter;$VERSION='1.04';@ISA=qw(Exporter);@EXPORT=qw(shell_quote shell_quote_best_effort shell_comment_quote);sub croak {require Carp;goto&Carp::croak}sub _shell_quote_backend {my@in=@_;my@err=();if (0){require RS::Handy;print RS::Handy::data_dump(\@in)}return \@err,'' unless@in;my$ret='';my$saw_non_equal=0;for (@in){if (!defined $_ or $_ eq ''){$_="''";next}if (s/\x00//g){push@err,"No way to quote string containing null (\\000) bytes"}my$escape=0;if (/=/){if (!$saw_non_equal){$escape=1}}else {$saw_non_equal=1}if (m|[^\w!%+,\-./:=@^]|){$escape=1}if ($escape || (!$saw_non_equal && /=/)){s/'/'\\''/g;s|((?:'\\''){2,})|q{'"} . (q{'} x (length($1) / 4)) . q{"'}|ge;$_="'$_'";s/^''//;s/''$//}}continue {$ret .= "$_ "}chop$ret;return \@err,$ret}sub shell_quote {my ($rerr,$s)=_shell_quote_backend @_;if (@$rerr){my%seen;@$rerr=grep {!$seen{$_}++}@$rerr;my$s=join '',map {"shell_quote(): $_\n"}@$rerr;chomp$s;croak$s}return$s}sub shell_quote_best_effort {my ($rerr,$s)=_shell_quote_backend @_;return$s}sub shell_comment_quote {return '' unless @_;unless (@_==1){croak "Too many arguments to shell_comment_quote " ."(got " .@_ ." expected 1)"}local $_=shift;s/\n/\n#/g;return $_}1;
 STRING_SHELLQUOTE
 
-$fatpacked{"aliased.pm"} = <<'ALIASED';
+$fatpacked{"aliased.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ALIASED';
   package aliased;our$VERSION='0.31';$VERSION=eval$VERSION;require Exporter;@ISA=qw(Exporter);@EXPORT=qw(alias prefix);use strict;sub _croak {require Carp;Carp::croak(@_)}sub import {my ($class,$package,$alias,@import)=@_;if (@_ <= 1){$class->export_to_level(1);return}my$callpack=caller(0);_load_alias($package,$callpack,@import);_make_alias($package,$callpack,$alias)}sub _get_alias {my$package=shift;$package =~ s/.*(?:::|')//;return$package}sub _make_alias {my ($package,$callpack,$alias)=@_;$alias ||=_get_alias($package);my$destination=$alias =~ /::/ ? $alias : "$callpack\::$alias";no strict 'refs';*{$destination}=sub () {$package}}sub _load_alias {my ($package,$callpack,@import)=@_;my$sigdie=$SIG{__DIE__};{my$code=@import==0 ? "package $callpack; use $package;" : "package $callpack; use $package (\@import)";eval$code;if (my$error=$@){$SIG{__DIE__}=$sigdie;_croak($error)}$sigdie=$SIG{__DIE__}if defined$SIG{__DIE__}}$SIG{__DIE__}=$sigdie if defined$sigdie;return$package}sub alias {my ($package,@import)=@_;my$callpack=scalar caller(0);return _load_alias($package,$callpack,@import)}sub prefix {my ($class)=@_;return sub {my ($name)=@_;my$callpack=caller(0);if (not @_){return _load_alias($class,$callpack)}elsif (@_==1 && defined$name){return _load_alias("${class}::$name",$callpack)}else {_croak("Too many arguments to prefix('$class')")}}}1;
 ALIASED
 
-$fatpacked{"lib/core/only.pm"} = <<'LIB_CORE_ONLY';
+$fatpacked{"lib/core/only.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIB_CORE_ONLY';
   package lib::core::only;use strict;use warnings FATAL=>'all';use Config;sub import {@INC=@Config{qw(privlibexp archlibexp)};return}1;
 LIB_CORE_ONLY
 
-$fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
-  use strict;use warnings;package local::lib;use 5.008001;use File::Spec ();use File::Path ();use Config;our$VERSION='1.008011';our@KNOWN_FLAGS=qw(--self-contained --deactivate --deactivate-all);sub DEACTIVATE_ONE () {1}sub DEACTIVATE_ALL () {2}sub INTERPOLATE_ENV () {1}sub LITERAL_ENV () {0}sub import {my ($class,@args)=@_;my$perl5lib=$ENV{PERL5LIB}|| '';my%arg_store;for my$arg (@args){if ($arg =~ /−/){die <<'DEATH'}elsif(grep {$arg eq $_}@KNOWN_FLAGS){(my$flag=$arg)=~ s/--//;$arg_store{$flag}=1}elsif($arg =~ /^--/){die "Unknown import argument: $arg"}else {$arg_store{path}=$arg}}if($arg_store{'self-contained'}){die "FATAL: The local::lib --self-contained flag has never worked reliably and the original author, Mark Stosberg, was unable or unwilling to maintain it. As such, this flag has been removed from the local::lib codebase in order to prevent misunderstandings and potentially broken builds. The local::lib authors recommend that you look at the lib::core::only module shipped with this distribution in order to create a more robust environment that is equivalent to what --self-contained provided (although quite possibly not what you originally thought it provided due to the poor quality of the documentation, for which we apologise).\n"}my$deactivating=0;if ($arg_store{deactivate}){$deactivating=DEACTIVATE_ONE}if ($arg_store{'deactivate-all'}){$deactivating=DEACTIVATE_ALL}$arg_store{path}=$class->resolve_path($arg_store{path});$class->setup_local_lib_for($arg_store{path},$deactivating);for (@INC){next if ref;m/(.*)/ and $_=$1}}sub pipeline;sub pipeline {my@methods=@_;my$last=pop(@methods);if (@methods){\sub {my ($obj,@args)=@_;$obj->${pipeline@methods}($obj->$last(@args))}}else {\sub {shift->$last(@_)}}}sub _uniq {my%seen;grep {!$seen{$_}++}@_}sub resolve_path {my ($class,$path)=@_;$class->${pipeline qw(resolve_relative_path resolve_home_path resolve_empty_path)}($path)}sub resolve_empty_path {my ($class,$path)=@_;if (defined$path){$path}else {'~/perl5'}}sub resolve_home_path {my ($class,$path)=@_;return$path unless ($path =~ /^~/);my ($user)=($path =~ /^~([^\/]+)/);my$tried_file_homedir;my$homedir=do {if (eval {require File::HomeDir}&& $File::HomeDir::VERSION >= 0.65){$tried_file_homedir=1;if (defined$user){File::HomeDir->users_home($user)}else {File::HomeDir->my_home}}else {if (defined$user){(getpwnam$user)[7]}else {if (defined$ENV{HOME}){$ENV{HOME}}else {(getpwuid $<)[7]}}}};unless (defined$homedir){require Carp;Carp::croak("Couldn't resolve homedir for " .(defined$user ? $user : 'current user').($tried_file_homedir ? '' : ' - consider installing File::HomeDir'))}$path =~ s/^~[^\/]*/$homedir/;$path}sub resolve_relative_path {my ($class,$path)=@_;$path=File::Spec->rel2abs($path)}sub setup_local_lib_for {my ($class,$path,$deactivating)=@_;my$interpolate=LITERAL_ENV;my@active_lls=$class->active_paths;$class->ensure_dir_structure_for($path);$path=Win32::GetShortPathName($path)if $^O eq 'MSWin32';if (!$deactivating){if (@active_lls && $active_lls[-1]eq $path){exit 0 if $0 eq '-';return}elsif (grep {$_ eq $path}@active_lls){$class->setup_env_hash_for($path,DEACTIVATE_ONE);$interpolate=INTERPOLATE_ENV}}if ($0 eq '-'){$class->print_environment_vars_for($path,$deactivating,$interpolate);exit 0}else {$class->setup_env_hash_for($path,$deactivating);my$arch_dir=$Config{archname};@INC=_uniq((map {(File::Spec->catdir($_,$arch_dir),$_)}split($Config{path_sep},$ENV{PERL5LIB})),@INC)}}sub install_base_bin_path {my ($class,$path)=@_;File::Spec->catdir($path,'bin')}sub install_base_perl_path {my ($class,$path)=@_;File::Spec->catdir($path,'lib','perl5')}sub install_base_arch_path {my ($class,$path)=@_;File::Spec->catdir($class->install_base_perl_path($path),$Config{archname})}sub ensure_dir_structure_for {my ($class,$path)=@_;unless (-d $path){warn "Attempting to create directory ${path}\n"}File::Path::mkpath($path);return}sub guess_shelltype {my$shellbin='sh';if(defined$ENV{'SHELL'}){my@shell_bin_path_parts=File::Spec->splitpath($ENV{'SHELL'});$shellbin=$shell_bin_path_parts[-1]}my$shelltype=do {local $_=$shellbin;if(/csh/){'csh'}else {'bourne'}};if (defined$ENV{'COMSPEC'}&& $^O ne 'cygwin'){my@shell_bin_path_parts=File::Spec->splitpath($ENV{'COMSPEC'});$shellbin=$shell_bin_path_parts[-1];$shelltype=do {local $_=$shellbin;if(/command\.com/){'win32'}elsif(/cmd\.exe/){'win32'}elsif(/4nt\.exe/){'win32'}else {$shelltype}}}return$shelltype}sub print_environment_vars_for {my ($class,$path,$deactivating,$interpolate)=@_;print$class->environment_vars_string_for($path,$deactivating,$interpolate)}sub environment_vars_string_for {my ($class,$path,$deactivating,$interpolate)=@_;my@envs=$class->build_environment_vars_for($path,$deactivating,$interpolate);my$out='';my$shelltype=$class->guess_shelltype;while (@envs){my ($name,$value)=(shift(@envs),shift(@envs));$value =~ s/(\\")/\\$1/g if defined$value;$out .= $class->${\"build_${shelltype}_env_declaration"}($name,$value)}return$out}sub build_bourne_env_declaration {my$class=shift;my($name,$value)=@_;return defined($value)? qq{export ${name}="${value}";\n} : qq{unset ${name};\n}}sub build_csh_env_declaration {my$class=shift;my($name,$value)=@_;return defined($value)? qq{setenv ${name} "${value}"\n} : qq{unsetenv ${name}\n}}sub build_win32_env_declaration {my$class=shift;my($name,$value)=@_;return defined($value)? qq{set ${name}=${value}\n} : qq{set ${name}=\n}}sub setup_env_hash_for {my ($class,$path,$deactivating)=@_;my%envs=$class->build_environment_vars_for($path,$deactivating,INTERPOLATE_ENV);@ENV{keys%envs}=values%envs}sub build_environment_vars_for {my ($class,$path,$deactivating,$interpolate)=@_;if ($deactivating==DEACTIVATE_ONE){return$class->build_deactivate_environment_vars_for($path,$interpolate)}elsif ($deactivating==DEACTIVATE_ALL){return$class->build_deact_all_environment_vars_for($path,$interpolate)}else {return$class->build_activate_environment_vars_for($path,$interpolate)}}my%ENV_LIST_VALUE_DEFAULTS=(interpolate=>INTERPOLATE_ENV,exists=>undef,filter=>sub {1},empty=>undef,);sub _env_list_value {my$options=shift;die(sprintf "unknown option '$_' at %s line %u\n",(caller)[1..2])for grep {!exists$ENV_LIST_VALUE_DEFAULTS{$_}}keys %$options;my%options=(%ENV_LIST_VALUE_DEFAULTS,%{$options});$options{exists}=$options{interpolate}==INTERPOLATE_ENV unless defined$options{exists};my%seen;my$value=join($Config{path_sep},map {ref $_ ? ($^O eq 'MSWin32' ? "%${$_}%" : "\$${$_}"): $_}grep {ref $_ || (defined $_ && length($_)> 0 &&!$seen{$_}++ && $options{filter}->($_)&& (!$options{exists}|| -e $_))}map {if (ref $_ eq 'SCALAR' && $options{interpolate}==INTERPOLATE_ENV){defined$ENV{${$_}}? (split /\Q$Config{path_sep}/,$ENV{${$_}}): ()}else {$_}}@_);return length($value)? $value : $options{empty}}sub build_activate_environment_vars_for {my ($class,$path,$interpolate)=@_;return (PERL_LOCAL_LIB_ROOT=>_env_list_value({interpolate=>$interpolate,exists=>0,empty=>'' },\'PERL_LOCAL_LIB_ROOT',$path,),PERL_MB_OPT=>"--install_base ${path}",PERL_MM_OPT=>"INSTALL_BASE=${path}",PERL5LIB=>_env_list_value({interpolate=>$interpolate,exists=>0,empty=>'' },$class->install_base_perl_path($path),\'PERL5LIB',),PATH=>_env_list_value({interpolate=>$interpolate,exists=>0,empty=>'' },$class->install_base_bin_path($path),\'PATH',),)}sub active_paths {my ($class)=@_;return ()unless defined$ENV{PERL_LOCAL_LIB_ROOT};return grep {$_ ne ''}split /\Q$Config{path_sep}/,$ENV{PERL_LOCAL_LIB_ROOT}}sub build_deactivate_environment_vars_for {my ($class,$path,$interpolate)=@_;my@active_lls=$class->active_paths;if (!grep {$_ eq $path}@active_lls){warn "Tried to deactivate inactive local::lib '$path'\n";return ()}my$perl_path=$class->install_base_perl_path($path);my$arch_path=$class->install_base_arch_path($path);my$bin_path=$class->install_base_bin_path($path);my%env=(PERL_LOCAL_LIB_ROOT=>_env_list_value({exists=>0,},grep {$_ ne $path}@active_lls),PERL5LIB=>_env_list_value({exists=>0,filter=>sub {$_ ne $perl_path && $_ ne $arch_path},},\'PERL5LIB',),PATH=>_env_list_value({exists=>0,filter=>sub {$_ ne $bin_path},},\'PATH',),);if ($active_lls[-1]eq $path){my$new_top=$active_lls[-2];$env{PERL_MB_OPT}=defined($new_top)? "--install_base ${new_top}" : undef;$env{PERL_MM_OPT}=defined($new_top)? "INSTALL_BASE=${new_top}" : undef}return%env}sub build_deact_all_environment_vars_for {my ($class,$path,$interpolate)=@_;my@active_lls=$class->active_paths;my%perl_paths=map {($class->install_base_perl_path($_)=>1,$class->install_base_arch_path($_)=>1)}@active_lls;my%bin_paths=map {($class->install_base_bin_path($_)=>1,)}@active_lls;my%env=(PERL_LOCAL_LIB_ROOT=>undef,PERL_MM_OPT=>undef,PERL_MB_OPT=>undef,PERL5LIB=>_env_list_value({exists=>0,filter=>sub {!scalar grep {exists$perl_paths{$_}}$_[0]},},\'PERL5LIB'),PATH=>_env_list_value({exists=>0,filter=>sub {!scalar grep {exists$bin_paths{$_}}$_[0]},},\'PATH'),);return%env}1;
+$fatpacked{"local/lib.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LOCAL_LIB';
+  package local::lib;use 5.006;use strict;use warnings;use Config;use File::Spec ();our$VERSION='2.000008';$VERSION=eval$VERSION;sub import {my ($class,@args)=@_;push@args,@ARGV if $0 eq '-';my@steps;my%opts;my$shelltype;while (@args){my$arg=shift@args;if ($arg =~ /\xE2\x88\x92/ or $arg =~ /−/){die <<'DEATH'}elsif ($arg eq '--self-contained'){die <<'DEATH'}elsif($arg =~ /^--deactivate(?:=(.*))?$/){my$path=defined $1 ? $1 : shift@args;push@steps,['deactivate',$path]}elsif ($arg eq '--deactivate-all'){push@steps,['deactivate_all']}elsif ($arg =~ /^--shelltype(?:=(.*))?$/){$shelltype=defined $1 ? $1 : shift@args}elsif ($arg eq '--no-create'){$opts{no_create}=1}elsif ($arg =~ /^--/){die "Unknown import argument: $arg"}else {push@steps,['activate',$arg]}}if (!@steps){push@steps,['activate',undef]}my$self=$class->new(%opts);for (@steps){my ($method,@args)=@$_;$self=$self->$method(@args)}if ($0 eq '-'){print$self->environment_vars_string($shelltype);exit 0}else {$self->setup_local_lib}}sub new {my$class=shift;bless {@_},$class}sub clone {my$self=shift;bless {%$self,@_},ref$self}sub inc {$_[0]->{inc}||=\@INC}sub libs {$_[0]->{libs}||=[\'PERL5LIB' ]}sub bins {$_[0]->{bins}||=[\'PATH' ]}sub roots {$_[0]->{roots}||=[\'PERL_LOCAL_LIB_ROOT' ]}sub extra {$_[0]->{extra}||={}}sub no_create {$_[0]->{no_create}}my$_archname=$Config{archname};my$_version=$Config{version};my@_inc_version_list=reverse split / /,$Config{inc_version_list};my$_path_sep=$Config{path_sep};sub _as_list {my$list=shift;grep length,map {!(ref $_ && ref $_ eq 'SCALAR')? $_ : (defined$ENV{$$_}? split(/\Q$_path_sep/,$ENV{$$_}): ())}ref$list ? @$list : $list}sub _remove_from {my ($list,@remove)=@_;return @$list if!@remove;my%remove=map {$_=>1}@remove;grep!$remove{$_},_as_list($list)}my@_lib_subdirs=([$_version,$_archname],[$_version],[$_archname],(@_inc_version_list ? \@_inc_version_list : ()),[],);sub install_base_bin_path {my ($class,$path)=@_;return File::Spec->catdir($path,'bin')}sub install_base_perl_path {my ($class,$path)=@_;return File::Spec->catdir($path,'lib','perl5')}sub install_base_arch_path {my ($class,$path)=@_;File::Spec->catdir($class->install_base_perl_path($path),$_archname)}sub lib_paths_for {my ($class,$path)=@_;my$base=$class->install_base_perl_path($path);return map {File::Spec->catdir($base,@$_)}@_lib_subdirs}sub _mm_escape_path {my$path=shift;$path =~ s/\\/\\\\\\\\/g;if ($path =~ s/ /\\ /g){$path=qq{"\\"$path\\""}}return$path}sub _mb_escape_path {my$path=shift;$path =~ s/\\/\\\\/g;return qq{"$path"}}sub installer_options_for {my ($class,$path)=@_;return (PERL_MM_OPT=>defined$path ? "INSTALL_BASE="._mm_escape_path($path): undef,PERL_MB_OPT=>defined$path ? "--install_base "._mb_escape_path($path): undef,)}sub active_paths {my ($self)=@_;$self=ref$self ? $self : $self->new;return grep {my$active_ll=$self->install_base_perl_path($_);grep {$_ eq $active_ll}@{$self->inc}}_as_list($self->roots)}sub deactivate {my ($self,$path)=@_;$self=$self->new unless ref$self;$path=$self->resolve_path($path);$path=$self->normalize_path($path);my@active_lls=$self->active_paths;if (!grep {$_ eq $path}@active_lls){warn "Tried to deactivate inactive local::lib '$path'\n";return$self}my%args=(bins=>[_remove_from($self->bins,$self->install_base_bin_path($path))],libs=>[_remove_from($self->libs,$self->install_base_perl_path($path))],inc=>[_remove_from($self->inc,$self->lib_paths_for($path))],roots=>[_remove_from($self->roots,$path)],);$args{extra}={$self->installer_options_for($args{roots}[0])};$self->clone(%args)}sub deactivate_all {my ($self)=@_;$self=$self->new unless ref$self;my@active_lls=$self->active_paths;my%args;if (@active_lls){%args=(bins=>[_remove_from($self->bins,map$self->install_base_bin_path($_),@active_lls)],libs=>[_remove_from($self->libs,map$self->install_base_perl_path($_),@active_lls)],inc=>[_remove_from($self->inc,map$self->lib_paths_for($_),@active_lls)],roots=>[_remove_from($self->roots,@active_lls)],)}$args{extra}={$self->installer_options_for(undef)};$self->clone(%args)}sub activate {my ($self,$path)=@_;$self=$self->new unless ref$self;$path=$self->resolve_path($path);$self->ensure_dir_structure_for($path)unless$self->no_create;$path=$self->normalize_path($path);my@active_lls=$self->active_paths;if (grep {$_ eq $path}@active_lls[1 .. $#active_lls]){$self=$self->deactivate($path)}my%args;if (!@active_lls || $active_lls[0]ne $path){%args=(bins=>[$self->install_base_bin_path($path),@{$self->bins}],libs=>[$self->install_base_perl_path($path),@{$self->libs}],inc=>[$self->lib_paths_for($path),@{$self->inc}],roots=>[$path,@{$self->roots}],)}$args{extra}={$self->installer_options_for($path)};$self->clone(%args)}sub normalize_path {my ($self,$path)=@_;$path=(Win32::GetShortPathName($path)|| $path)if $^O eq 'MSWin32';return$path}sub build_environment_vars_for {my$self=$_[0]->new->activate($_[1]);$self->build_environment_vars}sub build_environment_vars {my$self=shift;(PATH=>join($_path_sep,_as_list($self->bins)),PERL5LIB=>join($_path_sep,_as_list($self->libs)),PERL_LOCAL_LIB_ROOT=>join($_path_sep,_as_list($self->roots)),%{$self->extra},)}sub setup_local_lib_for {my$self=$_[0]->new->activate($_[1]);$self->setup_local_lib}sub setup_local_lib {my$self=shift;$self->setup_env_hash;@INC=@{$self->inc}}sub setup_env_hash_for {my$self=$_[0]->new->activate($_[1]);$self->setup_env_hash}sub setup_env_hash {my$self=shift;my%env=$self->build_environment_vars;for my$key (keys%env){if (defined$env{$key}){$ENV{$key}=$env{$key}}else {delete$ENV{$key}}}}sub print_environment_vars_for {print $_[0]->environment_vars_string_for(@_[1..$#_])}sub environment_vars_string_for {my$self=$_[0]->new->activate($_[1]);$self->environment_vars_string}sub environment_vars_string {my ($self,$shelltype)=@_;$shelltype ||=$self->guess_shelltype;my$build_method="build_${shelltype}_env_declaration";my$extra=$self->extra;my@envs=(PATH=>$self->bins,PERL5LIB=>$self->libs,PERL_LOCAL_LIB_ROOT=>$self->roots,map {$_=>$extra->{$_}}sort keys %$extra,);my$out='';while (@envs){my ($name,$value)=(shift(@envs),shift(@envs));if (ref$value && @$value==1 && ref$value->[0]&& ref$value->[0]eq 'SCALAR' && ${$value->[0]}eq $name){next}if (!ref$value and defined$value ? (defined$ENV{$name}&& $value eq $ENV{$name}):!defined$ENV{$name}){next}$out .= $self->$build_method($name,$value)}my$wrap_method="wrap_${shelltype}_output";if ($self->can($wrap_method)){return$self->$wrap_method($out)}return$out}sub build_bourne_env_declaration {my ($class,$name,$args)=@_;my$value=$class->_interpolate($args,'$%s','"','\\%s');if (!defined$value){return qq{unset $name;\n}}$value =~ s/(^|\G|$_path_sep)\$$name$_path_sep/$1\$$name\${$name+$_path_sep}/g;$value =~ s/$_path_sep\$$name$/\${$name+$_path_sep}\$$name/;qq{${name}="$value"; export ${name};\n}}sub build_csh_env_declaration {my ($class,$name,$args)=@_;my ($value,@vars)=$class->_interpolate($args,'$%s','"','"\\%s"');if (!defined$value){return qq{unsetenv $name;\n}}my$out='';for my$var (@vars){$out .= qq{if ! \$?$name setenv $name '';\n}}my$value_without=$value;if ($value_without =~ s/(?:^|$_path_sep)\$$name(?:$_path_sep|$)//g){$out .= qq{if "\$$name" != '' setenv $name "$value";\n};$out .= qq{if "\$$name" == '' }}$out .= qq{setenv $name "$value_without";\n};return$out}sub build_cmd_env_declaration {my ($class,$name,$args)=@_;my$value=$class->_interpolate($args,'%%%s%%',qr([()!^"<>&|]),'^%s');if (!$value){return qq{\@set $name=\n}}my$out='';my$value_without=$value;if ($value_without =~ s/(?:^|$_path_sep)%$name%(?:$_path_sep|$)//g){$out .= qq{\@if not "%$name%"=="" set $name=$value\n};$out .= qq{\@if "%$name%"=="" }}$out .= qq{\@set $name=$value_without\n};return$out}sub build_powershell_env_declaration {my ($class,$name,$args)=@_;my$value=$class->_interpolate($args,'$env:%s','"','`%s');if (!$value){return qq{Remove-Item -ErrorAction 0 Env:\\$name;\n}}my$maybe_path_sep=qq{\$(if("\$env:$name"-eq""){""}else{"$_path_sep"})};$value =~ s/(^|\G|$_path_sep)\$env:$name$_path_sep/$1\$env:$name"+$maybe_path_sep+"/g;$value =~ s/$_path_sep\$env:$name$/"+$maybe_path_sep+\$env:$name+"/;qq{\$env:$name = \$("$value");\n}}sub wrap_powershell_output {my ($class,$out)=@_;return$out || " \n"}sub build_fish_env_declaration {my ($class,$name,$args)=@_;my$value=$class->_interpolate($args,'$%s','"','\\%s');if (!defined$value){return qq{set -e $name;\n}}$value =~ s/$_path_sep/ /g;qq{set -x $name $value;\n}}sub _interpolate {my ($class,$args,$var_pat,$escape,$escape_pat)=@_;return unless defined$args;my@args=ref$args ? @$args : $args;return unless@args;my@vars=map {$$_}grep {ref $_ eq 'SCALAR'}@args;my$string=join$_path_sep,map {ref $_ eq 'SCALAR' ? sprintf($var_pat,$$_): do {s/($escape)/sprintf($escape_pat, $1)/ge;$_}}@args;return wantarray ? ($string,\@vars): $string}sub pipeline;sub pipeline {my@methods=@_;my$last=pop(@methods);if (@methods){\sub {my ($obj,@args)=@_;$obj->${pipeline@methods}($obj->$last(@args))}}else {\sub {shift->$last(@_)}}}sub resolve_path {my ($class,$path)=@_;$path=$class->${pipeline qw(resolve_relative_path resolve_home_path resolve_empty_path)}($path);$path}sub resolve_empty_path {my ($class,$path)=@_;if (defined$path){$path}else {'~/perl5'}}sub resolve_home_path {my ($class,$path)=@_;$path =~ /^~([^\/]*)/ or return$path;my$user=$1;my$homedir=do {if (!length($user)&& defined$ENV{HOME}){$ENV{HOME}}else {require File::Glob;File::Glob::bsd_glob("~$user",File::Glob::GLOB_TILDE())}};unless (defined$homedir){require Carp;Carp::croak("Couldn't resolve homedir for " .(defined$user ? $user : 'current user'))}$path =~ s/^~[^\/]*/$homedir/;$path}sub resolve_relative_path {my ($class,$path)=@_;$path=File::Spec->rel2abs($path)}sub ensure_dir_structure_for {my ($class,$path)=@_;unless (-d $path){warn "Attempting to create directory ${path}\n"}require File::Basename;my@dirs;while(!-d $path){push@dirs,$path;$path=File::Basename::dirname($path)}mkdir $_ for reverse@dirs;return}sub guess_shelltype {my$shellbin =defined$ENV{SHELL}? ($ENV{SHELL}=~ /([\w.]+)$/)[-1]: ($^O eq 'MSWin32' && exists$ENV{'!EXITCODE'})? 'bash' : ($^O eq 'MSWin32' && $ENV{PROMPT}&& $ENV{COMSPEC})? ($ENV{COMSPEC}=~ /([\w.]+)$/)[-1]: ($^O eq 'MSWin32' &&!$ENV{PROMPT})? 'powershell.exe' : 'sh';for ($shellbin){return /csh$/ ? 'csh' : /fish/ ? 'fish' : /command(?:\.com)?$/i ? 'cmd' : /cmd(?:\.exe)?$/i ? 'cmd' : /4nt(?:\.exe)?$/i ? 'cmd' : /powershell(?:\.exe)?$/i ? 'powershell' : 'bourne'}}1;
   WHOA THERE! It looks like you've got some fancy dashes in your commandline!
   These are *not* the traditional -- dashes that software recognizes. You
   probably got these by copy-pasting from the perldoc for this module as
@@ -415,48 +416,79 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   terminal, but can happen elsewhere too. Please try again after replacing the
   dashes with normal minus signs.
   DEATH
+  FATAL: The local::lib --self-contained flag has never worked reliably and the
+  original author, Mark Stosberg, was unable or unwilling to maintain it. As
+  such, this flag has been removed from the local::lib codebase in order to
+  prevent misunderstandings and potentially broken builds. The local::lib authors
+  recommend that you look at the lib::core::only module shipped with this
+  distribution in order to create a more robust environment that is equivalent to
+  what --self-contained provided (although quite possibly not what you originally
+  thought it provided due to the poor quality of the documentation, for which we
+  apologise).
+  DEATH
 LOCAL_LIB
 
-$fatpacked{"version.pm"} = <<'VERSION';
-  package version;use 5.005_04;use strict;use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);$VERSION=0.9902;$CLASS='version';my$FRACTION_PART=qr/\.[0-9]+/;my$STRICT_INTEGER_PART=qr/0|[1-9][0-9]*/;my$LAX_INTEGER_PART=qr/[0-9]+/;my$STRICT_DOTTED_DECIMAL_PART=qr/\.[0-9]{1,3}/;my$LAX_DOTTED_DECIMAL_PART=qr/\.[0-9]+/;my$LAX_ALPHA_PART=qr/_[0-9]+/;my$STRICT_DECIMAL_VERSION=qr/ $STRICT_INTEGER_PART $FRACTION_PART? /x;my$STRICT_DOTTED_DECIMAL_VERSION=qr/ v $STRICT_INTEGER_PART $STRICT_DOTTED_DECIMAL_PART{2,} /x;$STRICT=qr/ $STRICT_DECIMAL_VERSION | $STRICT_DOTTED_DECIMAL_VERSION /x;my$LAX_DECIMAL_VERSION=qr/ $LAX_INTEGER_PART (?: \. | $FRACTION_PART $LAX_ALPHA_PART? )?
+$fatpacked{"parent.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PARENT';
+  package parent;use strict;use vars qw($VERSION);$VERSION='0.225';sub import {my$class=shift;my$inheritor=caller(0);if (@_ and $_[0]eq '-norequire'){shift @_}else {for (my@filename=@_){if ($_ eq $inheritor){warn "Class '$inheritor' tried to inherit from itself\n"};s{::|'}{/}g;require "$_.pm"}}{no strict 'refs';push @{"$inheritor\::ISA"},@_}};"All your base are belong to us" 
+PARENT
+
+$fatpacked{"version.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION';
+  package version;use 5.006002;use strict;use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);$VERSION=0.9908;$CLASS='version';{local$SIG{'__DIE__'};eval "use version::vxs $VERSION";if ($@){eval "use version::vpp $VERSION";die "$@" if ($@);push@ISA,"version::vpp";local $^W;*version::qv=\&version::vpp::qv;*version::declare=\&version::vpp::declare;*version::_VERSION=\&version::vpp::_VERSION;*version::vcmp=\&version::vpp::vcmp;*version::new=\&version::vpp::new;if ($] >= 5.009000){no strict 'refs';*version::stringify=\&version::vpp::stringify;*{'version::(""'}=\&version::vpp::stringify;*{'version::(<=>'}=\&version::vpp::vcmp;*version::parse=\&version::vpp::parse}}else {push@ISA,"version::vxs";local $^W;*version::declare=\&version::vxs::declare;*version::qv=\&version::vxs::qv;*version::_VERSION=\&version::vxs::_VERSION;*version::vcmp=\&version::vxs::VCMP;*version::new=\&version::vxs::new;if ($] >= 5.009000){no strict 'refs';*version::stringify=\&version::vxs::stringify;*{'version::(""'}=\&version::vxs::stringify;*{'version::(<=>'}=\&version::vxs::VCMP;*version::parse=\&version::vxs::parse}}}require version::regex;*version::is_lax=\&version::regex::is_lax;*version::is_strict=\&version::regex::is_strict;*LAX=\$version::regex::LAX;*STRICT=\$version::regex::STRICT;sub import {no strict 'refs';my ($class)=shift;unless ($class eq $CLASS){local $^W;*{$class.'::declare'}=\&{$CLASS.'::declare'};*{$class.'::qv'}=\&{$CLASS.'::qv'}}my%args;if (@_){map {$args{$_}=1}@_}else {%args=(qv=>1,'UNIVERSAL::VERSION'=>1,)}my$callpkg=caller();if (exists($args{declare})){*{$callpkg.'::declare'}=sub {return$class->declare(shift)}unless defined(&{$callpkg.'::declare'})}if (exists($args{qv})){*{$callpkg.'::qv'}=sub {return$class->qv(shift)}unless defined(&{$callpkg.'::qv'})}if (exists($args{'UNIVERSAL::VERSION'})){local $^W;*UNIVERSAL::VERSION =\&{$CLASS.'::_VERSION'}}if (exists($args{'VERSION'})){*{$callpkg.'::VERSION'}=\&{$CLASS.'::_VERSION'}}if (exists($args{'is_strict'})){*{$callpkg.'::is_strict'}=\&{$CLASS.'::is_strict'}unless defined(&{$callpkg.'::is_strict'})}if (exists($args{'is_lax'})){*{$callpkg.'::is_lax'}=\&{$CLASS.'::is_lax'}unless defined(&{$callpkg.'::is_lax'})}}1;
+VERSION
+
+$fatpacked{"version/regex.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION_REGEX';
+  package version::regex;use strict;use vars qw($VERSION $CLASS $STRICT $LAX);$VERSION=0.9908;my$FRACTION_PART=qr/\.[0-9]+/;my$STRICT_INTEGER_PART=qr/0|[1-9][0-9]*/;my$LAX_INTEGER_PART=qr/[0-9]+/;my$STRICT_DOTTED_DECIMAL_PART=qr/\.[0-9]{1,3}/;my$LAX_DOTTED_DECIMAL_PART=qr/\.[0-9]+/;my$LAX_ALPHA_PART=qr/_[0-9]+/;my$STRICT_DECIMAL_VERSION=qr/ $STRICT_INTEGER_PART $FRACTION_PART? /x;my$STRICT_DOTTED_DECIMAL_VERSION=qr/ v $STRICT_INTEGER_PART $STRICT_DOTTED_DECIMAL_PART{2,} /x;$STRICT=qr/ $STRICT_DECIMAL_VERSION | $STRICT_DOTTED_DECIMAL_VERSION /x;my$LAX_DECIMAL_VERSION=qr/ $LAX_INTEGER_PART (?: \. | $FRACTION_PART $LAX_ALPHA_PART? )?
   	|
   	$FRACTION_PART $LAX_ALPHA_PART?
       /x;my$LAX_DOTTED_DECIMAL_VERSION=qr/
   	v $LAX_INTEGER_PART (?: $LAX_DOTTED_DECIMAL_PART+ $LAX_ALPHA_PART? )?
   	|
   	$LAX_INTEGER_PART? $LAX_DOTTED_DECIMAL_PART{2,} $LAX_ALPHA_PART?
-      /x;$LAX=qr/ undef | $LAX_DECIMAL_VERSION | $LAX_DOTTED_DECIMAL_VERSION /x;{local$SIG{'__DIE__'};eval "use version::vxs $VERSION";if ($@){eval "use version::vpp $VERSION";die "$@" if ($@);push@ISA,"version::vpp";local $^W;*version::qv=\&version::vpp::qv;*version::declare=\&version::vpp::declare;*version::_VERSION=\&version::vpp::_VERSION;*version::vcmp=\&version::vpp::vcmp;*version::new=\&version::vpp::new;if ($] >= 5.009000){no strict 'refs';*version::stringify=\&version::vpp::stringify;*{'version::(""'}=\&version::vpp::stringify;*{'version::(<=>'}=\&version::vpp::vcmp;*version::parse=\&version::vpp::parse}}else {push@ISA,"version::vxs";local $^W;*version::declare=\&version::vxs::declare;*version::qv=\&version::vxs::qv;*version::_VERSION=\&version::vxs::_VERSION;*version::vcmp=\&version::vxs::VCMP;*version::new=\&version::vxs::new;if ($] >= 5.009000){no strict 'refs';*version::stringify=\&version::vxs::stringify;*{'version::(""'}=\&version::vxs::stringify;*{'version::(<=>'}=\&version::vxs::VCMP;*version::parse=\&version::vxs::parse}}}sub import {no strict 'refs';my ($class)=shift;unless ($class eq 'version'){local $^W;*{$class.'::declare'}=\&version::declare;*{$class.'::qv'}=\&version::qv}my%args;if (@_){map {$args{$_}=1}@_}else {%args=(qv=>1,'UNIVERSAL::VERSION'=>1,)}my$callpkg=caller();if (exists($args{declare})){*{$callpkg.'::declare'}=sub {return$class->declare(shift)}unless defined(&{$callpkg.'::declare'})}if (exists($args{qv})){*{$callpkg.'::qv'}=sub {return$class->qv(shift)}unless defined(&{$callpkg.'::qv'})}if (exists($args{'UNIVERSAL::VERSION'})){local $^W;*UNIVERSAL::VERSION =\&version::_VERSION}if (exists($args{'VERSION'})){*{$callpkg.'::VERSION'}=\&version::_VERSION}if (exists($args{'is_strict'})){*{$callpkg.'::is_strict'}=\&version::is_strict unless defined(&{$callpkg.'::is_strict'})}if (exists($args{'is_lax'})){*{$callpkg.'::is_lax'}=\&version::is_lax unless defined(&{$callpkg.'::is_lax'})}}sub is_strict {defined $_[0]&& $_[0]=~ qr/ \A $STRICT \z /x}sub is_lax {defined $_[0]&& $_[0]=~ qr/ \A $LAX \z /x}1;
-VERSION
+      /x;$LAX=qr/ undef | $LAX_DECIMAL_VERSION | $LAX_DOTTED_DECIMAL_VERSION /x;sub is_strict {defined $_[0]&& $_[0]=~ qr/ \A $STRICT \z /x}sub is_lax {defined $_[0]&& $_[0]=~ qr/ \A $LAX \z /x}1;
+VERSION_REGEX
 
-$fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
-  package charstar;use overload ('""'=>\&thischar,'0+'=>\&thischar,'++'=>\&increment,'--'=>\&decrement,'+'=>\&plus,'-'=>\&minus,'*'=>\&multiply,'cmp'=>\&cmp,'<=>'=>\&spaceship,'bool'=>\&thischar,'='=>\&clone,);sub new {my ($self,$string)=@_;my$class=ref($self)|| $self;my$obj={string=>[split(//,$string)],current=>0,};return bless$obj,$class}sub thischar {my ($self)=@_;my$last=$#{$self->{string}};my$curr=$self->{current};if ($curr >= 0 && $curr <= $last){return$self->{string}->[$curr]}else {return ''}}sub increment {my ($self)=@_;$self->{current}++}sub decrement {my ($self)=@_;$self->{current}--}sub plus {my ($self,$offset)=@_;my$rself=$self->clone;$rself->{current}+= $offset;return$rself}sub minus {my ($self,$offset)=@_;my$rself=$self->clone;$rself->{current}-= $offset;return$rself}sub multiply {my ($left,$right,$swapped)=@_;my$char=$left->thischar();return$char * $right}sub spaceship {my ($left,$right,$swapped)=@_;unless (ref($right)){$right=$left->new($right)}return$left->{current}<=> $right->{current}}sub cmp {my ($left,$right,$swapped)=@_;unless (ref($right)){if (length($right)==1){return$left->thischar cmp $right}$right=$left->new($right)}return$left->currstr cmp $right->currstr}sub bool {my ($self)=@_;my$char=$self->thischar;return ($char ne '')}sub clone {my ($left,$right,$swapped)=@_;$right={string=>[@{$left->{string}}],current=>$left->{current},};return bless$right,ref($left)}sub currstr {my ($self,$s)=@_;my$curr=$self->{current};my$last=$#{$self->{string}};if (defined($s)&& $s->{current}< $last){$last=$s->{current}}my$string=join('',@{$self->{string}}[$curr..$last]);return$string}package version::vpp;use strict;use POSIX qw/locale_h/;use locale;use vars qw ($VERSION @ISA @REGEXS);$VERSION=0.9902;use overload ('""'=>\&stringify,'0+'=>\&numify,'cmp'=>\&vcmp,'<=>'=>\&vcmp,'bool'=>\&vbool,'+'=>\&vnoop,'-'=>\&vnoop,'*'=>\&vnoop,'/'=>\&vnoop,'+='=>\&vnoop,'-='=>\&vnoop,'*='=>\&vnoop,'/='=>\&vnoop,'abs'=>\&vnoop,);eval "use warnings";if ($@){eval '
+$fatpacked{"version/vpp.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION_VPP';
+  package charstar;use overload ('""'=>\&thischar,'0+'=>\&thischar,'++'=>\&increment,'--'=>\&decrement,'+'=>\&plus,'-'=>\&minus,'*'=>\&multiply,'cmp'=>\&cmp,'<=>'=>\&spaceship,'bool'=>\&thischar,'='=>\&clone,);sub new {my ($self,$string)=@_;my$class=ref($self)|| $self;my$obj={string=>[split(//,$string)],current=>0,};return bless$obj,$class}sub thischar {my ($self)=@_;my$last=$#{$self->{string}};my$curr=$self->{current};if ($curr >= 0 && $curr <= $last){return$self->{string}->[$curr]}else {return ''}}sub increment {my ($self)=@_;$self->{current}++}sub decrement {my ($self)=@_;$self->{current}--}sub plus {my ($self,$offset)=@_;my$rself=$self->clone;$rself->{current}+= $offset;return$rself}sub minus {my ($self,$offset)=@_;my$rself=$self->clone;$rself->{current}-= $offset;return$rself}sub multiply {my ($left,$right,$swapped)=@_;my$char=$left->thischar();return$char * $right}sub spaceship {my ($left,$right,$swapped)=@_;unless (ref($right)){$right=$left->new($right)}return$left->{current}<=> $right->{current}}sub cmp {my ($left,$right,$swapped)=@_;unless (ref($right)){if (length($right)==1){return$left->thischar cmp $right}$right=$left->new($right)}return$left->currstr cmp $right->currstr}sub bool {my ($self)=@_;my$char=$self->thischar;return ($char ne '')}sub clone {my ($left,$right,$swapped)=@_;$right={string=>[@{$left->{string}}],current=>$left->{current},};return bless$right,ref($left)}sub currstr {my ($self,$s)=@_;my$curr=$self->{current};my$last=$#{$self->{string}};if (defined($s)&& $s->{current}< $last){$last=$s->{current}}my$string=join('',@{$self->{string}}[$curr..$last]);return$string}package version::vpp;use 5.006002;use strict;use Config;use vars qw($VERSION $CLASS @ISA $LAX $STRICT);$VERSION=0.9908;$CLASS='version::vpp';require version::regex;*version::vpp::is_strict=\&version::regex::is_strict;*version::vpp::is_lax=\&version::regex::is_lax;*LAX=\$version::regex::LAX;*STRICT=\$version::regex::STRICT;use overload ('""'=>\&stringify,'0+'=>\&numify,'cmp'=>\&vcmp,'<=>'=>\&vcmp,'bool'=>\&vbool,'+'=>\&vnoop,'-'=>\&vnoop,'*'=>\&vnoop,'/'=>\&vnoop,'+='=>\&vnoop,'-='=>\&vnoop,'*='=>\&vnoop,'/='=>\&vnoop,'abs'=>\&vnoop,);eval "use warnings";if ($@){eval '
   	package
   	warnings;
   	sub enabled {return $^W;}
   	1;
-      '}my$VERSION_MAX=0x7FFFFFFF;use constant TRUE=>1;use constant FALSE=>0;sub isDIGIT {my ($char)=shift->thischar();return ($char =~ /\d/)}sub isALPHA {my ($char)=shift->thischar();return ($char =~ /[a-zA-Z]/)}sub isSPACE {my ($char)=shift->thischar();return ($char =~ /\s/)}sub BADVERSION {my ($s,$errstr,$error)=@_;if ($errstr){$$errstr=$error}return$s}sub prescan_version {my ($s,$strict,$errstr,$sqv,$ssaw_decimal,$swidth,$salpha)=@_;my$qv=defined$sqv ? $$sqv : FALSE;my$saw_decimal=defined$ssaw_decimal ? $$ssaw_decimal : 0;my$width=defined$swidth ? $$swidth : 3;my$alpha=defined$salpha ? $$salpha : FALSE;my$d=$s;if ($qv && isDIGIT($d)){goto dotted_decimal_version}if ($d eq 'v'){$d++;if (isDIGIT($d)){$qv=TRUE}else {return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}dotted_decimal_version: if ($strict && $d eq '0' && isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)")}while (isDIGIT($d)){$d++}if ($d eq '.'){$saw_decimal++;$d++}else {if ($strict){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}else {goto version_prescan_finish}}{my$i=0;my$j=0;while (isDIGIT($d)){$i++;while (isDIGIT($d)){$d++;$j++;if ($strict && $j > 3){return BADVERSION($s,$errstr,"Invalid version format (maximum 3 digits between decimals)")}}if ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)")}$d++;$alpha=TRUE}elsif ($d eq '.'){if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)")}$saw_decimal++;$d++}elsif (!isDIGIT($d)){last}$j=0}if ($strict && $i < 2){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}}}else {my$j=0;if ($strict){if ($d eq '.'){return BADVERSION($s,$errstr,"Invalid version format (0 before decimal required)")}if ($d eq '0' && isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)")}}if ($d eq '-'){return BADVERSION($s,$errstr,"Invalid version format (negative version number)")}while (isDIGIT($d)){$d++}if ($d eq '.'){$saw_decimal++;$d++}elsif (!$d || $d eq ';' || isSPACE($d)|| $d eq '}'){if ($d==$s){return BADVERSION($s,$errstr,"Invalid version format (version required)")}goto version_prescan_finish}elsif ($d==$s){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}elsif ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}elsif (isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (alpha without decimal)")}else {return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)")}}elsif ($d){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}if ($d &&!isDIGIT($d)&& ($strict ||!($d eq ';' || isSPACE($d)|| $d eq '}'))){return BADVERSION($s,$errstr,"Invalid version format (fractional part required)")}while (isDIGIT($d)){$d++;$j++;if ($d eq '.' && isDIGIT($d-1)){if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)")}if ($strict){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions must begin with 'v')")}$d=$s;$qv=TRUE;goto dotted_decimal_version}if ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)")}if (!isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)")}$width=$j;$d++;$alpha=TRUE}}}version_prescan_finish: while (isSPACE($d)){$d++}if ($d &&!isDIGIT($d)&& (!($d eq ';' || $d eq '}'))){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}if (defined$sqv){$$sqv=$qv}if (defined$swidth){$$swidth=$width}if (defined$ssaw_decimal){$$ssaw_decimal=$saw_decimal}if (defined$salpha){$$salpha=$alpha}return$d}sub scan_version {my ($s,$rv,$qv)=@_;my$start;my$pos;my$last;my$errstr;my$saw_decimal=0;my$width=3;my$alpha=FALSE;my$vinf=FALSE;my@av;$s=new charstar$s;while (isSPACE($s)){$s++}$last=prescan_version($s,FALSE,\$errstr,\$qv,\$saw_decimal,\$width,\$alpha);if ($errstr){if ($s ne 'undef'){use Carp;Carp::croak($errstr)}}$start=$s;if ($s eq 'v'){$s++}$pos=$s;if ($qv){$$rv->{qv}=$qv}if ($alpha){$$rv->{alpha}=$alpha}if (!$qv && $width < 3){$$rv->{width}=$width}while (isDIGIT($pos)){$pos++}if (!isALPHA($pos)){my$rev;for (;;){$rev=0;{my$end=$pos;my$mult=1;my$orev;if (!$qv && $s > $start && $saw_decimal==1){$mult *= 100;while ($s < $end){$orev=$rev;$rev += $s * $mult;$mult /= 10;if ((abs($orev)> abs($rev))|| (abs($rev)> $VERSION_MAX)){warn("Integer overflow in version %d",$VERSION_MAX);$s=$end - 1;$rev=$VERSION_MAX;$vinf=1}$s++;if ($s eq '_'){$s++}}}else {while (--$end >= $s){$orev=$rev;$rev += $end * $mult;$mult *= 10;if ((abs($orev)> abs($rev))|| (abs($rev)> $VERSION_MAX)){warn("Integer overflow in version");$end=$s - 1;$rev=$VERSION_MAX;$vinf=1}}}}push@av,$rev;if ($vinf){$s=$last;last}elsif ($pos eq '.'){$s=++$pos}elsif ($pos eq '_' && isDIGIT($pos+1)){$s=++$pos}elsif ($pos eq ',' && isDIGIT($pos+1)){$s=++$pos}elsif (isDIGIT($pos)){$s=$pos}else {$s=$pos;last}if ($qv){while (isDIGIT($pos)){$pos++}}else {my$digits=0;while ((isDIGIT($pos)|| $pos eq '_')&& $digits < 3){if ($pos ne '_'){$digits++}$pos++}}}}if ($qv){my$len=$#av;$len=2 - $len;while ($len-- > 0){push@av,0}}if ($vinf){$$rv->{original}="v.Inf";$$rv->{vinf}=1}elsif ($s > $start){$$rv->{original}=$start->currstr($s);if ($qv && $saw_decimal==1 && $start ne 'v'){$$rv->{original}='v' .$$rv->{original}}}else {$$rv->{original}='0';push(@av,0)}$$rv->{version}=\@av;if ($s eq 'undef'){$s += 5}return$s}sub new {my ($class,$value)=@_;unless (defined$class){require Carp;Carp::croak('Usage: version::new(class, version)')}my$self=bless ({},ref ($class)|| $class);my$qv=FALSE;if (ref($value)&& eval('$value->isa("version")')){$self->{version}=[@{$value->{version}}];$self->{qv}=1 if$value->{qv};$self->{alpha}=1 if$value->{alpha};$self->{original}=''.$value->{original};return$self}my$currlocale=setlocale(LC_ALL);if (localeconv()->{decimal_point}eq ','){$value =~ tr/,/./}if (not defined$value or $value =~ /^undef$/){push @{$self->{version}},0;$self->{original}="0";return ($self)}if ($#_==2){$value=$_[2];$qv=TRUE}$value=_un_vstring($value);if ($value =~ /\d+.?\d*e[-+]?\d+/){$value=sprintf("%.9f",$value);$value =~ s/(0+)$//}my$s=scan_version($value,\$self,$qv);if ($s){warn("Version string '%s' contains invalid data; " ."ignoring: '%s'",$value,$s)}return ($self)}*parse=\&new;sub numify {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}my$width=$self->{width}|| 3;my$alpha=$self->{alpha}|| "";my$len=$#{$self->{version}};my$digit=$self->{version}[0];my$string=sprintf("%d.",$digit);for (my$i=1 ;$i < $len ;$i++ ){$digit=$self->{version}[$i];if ($width < 3){my$denom=10**(3-$width);my$quot=int($digit/$denom);my$rem=$digit - ($quot * $denom);$string .= sprintf("%0".$width."d_%d",$quot,$rem)}else {$string .= sprintf("%03d",$digit)}}if ($len > 0){$digit=$self->{version}[$len];if ($alpha && $width==3){$string .= "_"}$string .= sprintf("%0".$width."d",$digit)}else {$string .= sprintf("000")}return$string}sub normal {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}my$alpha=$self->{alpha}|| "";my$len=$#{$self->{version}};my$digit=$self->{version}[0];my$string=sprintf("v%d",$digit);for (my$i=1 ;$i < $len ;$i++ ){$digit=$self->{version}[$i];$string .= sprintf(".%d",$digit)}if ($len > 0){$digit=$self->{version}[$len];if ($alpha){$string .= sprintf("_%0d",$digit)}else {$string .= sprintf(".%0d",$digit)}}if ($len <= 2){for ($len=2 - $len;$len!=0;$len-- ){$string .= sprintf(".%0d",0)}}return$string}sub stringify {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}return exists$self->{original}? $self->{original}: exists$self->{qv}? $self->normal : $self->numify}sub vcmp {require UNIVERSAL;my ($left,$right,$swap)=@_;my$class=ref($left);unless (UNIVERSAL::isa($right,$class)){$right=$class->new($right)}if ($swap){($left,$right)=($right,$left)}unless (_verify($left)){require Carp;Carp::croak("Invalid version object")}unless (_verify($right)){require Carp;Carp::croak("Invalid version format")}my$l=$#{$left->{version}};my$r=$#{$right->{version}};my$m=$l < $r ? $l : $r;my$lalpha=$left->is_alpha;my$ralpha=$right->is_alpha;my$retval=0;my$i=0;while ($i <= $m && $retval==0){$retval=$left->{version}[$i]<=> $right->{version}[$i];$i++}if ($retval==0 && $l==$r && $left->{version}[$m]==$right->{version}[$m]&& ($lalpha || $ralpha)){if ($lalpha &&!$ralpha){$retval=-1}elsif ($ralpha &&!$lalpha){$retval=+1}}if ($retval==0 && $l!=$r){if ($l < $r){while ($i <= $r && $retval==0){if ($right->{version}[$i]!=0){$retval=-1}$i++}}else {while ($i <= $l && $retval==0){if ($left->{version}[$i]!=0){$retval=+1}$i++}}}return$retval}sub vbool {my ($self)=@_;return vcmp($self,$self->new("0"),1)}sub vnoop {require Carp;Carp::croak("operation not supported with version object")}sub is_alpha {my ($self)=@_;return (exists$self->{alpha})}sub qv {my$value=shift;my$class='version';if (@_){$class=ref($value)|| $value;$value=shift}$value=_un_vstring($value);$value='v'.$value unless$value =~ /(^v|\d+\.\d+\.\d)/;my$obj=version->new($value);return bless$obj,$class}*declare=\&qv;sub is_qv {my ($self)=@_;return (exists$self->{qv})}sub _verify {my ($self)=@_;if (ref($self)&& eval {exists$self->{version}}&& ref($self->{version})eq 'ARRAY'){return 1}else {return 0}}sub _is_non_alphanumeric {my$s=shift;$s=new charstar$s;while ($s){return 0 if isSPACE($s);return 1 unless (isALPHA($s)|| isDIGIT($s)|| $s =~ /[.-]/);$s++}return 0}sub _un_vstring {my$value=shift;if (length($value)>= 3 && $value !~ /[._]/ && _is_non_alphanumeric($value)){my$tvalue;if ($] ge 5.008_001){$tvalue=_find_magic_vstring($value);$value=$tvalue if length$tvalue}elsif ($] ge 5.006_000){$tvalue=sprintf("v%vd",$value);if ($tvalue =~ /^v\d+(\.\d+){2,}$/){$value=$tvalue}}}return$value}sub _find_magic_vstring {my$value=shift;my$tvalue='';require B;my$sv=B::svref_2object(\$value);my$magic=ref($sv)eq 'B::PVMG' ? $sv->MAGIC : undef;while ($magic){if ($magic->TYPE eq 'V'){$tvalue=$magic->PTR;$tvalue =~ s/^v?(.+)$/v$1/;last}else {$magic=$magic->MOREMAGIC}}return$tvalue}sub _VERSION {my ($obj,$req)=@_;my$class=ref($obj)|| $obj;no strict 'refs';if (exists$INC{"$class.pm"}and not %{"$class\::"}and $] >= 5.008){require Carp;Carp::croak("$class defines neither package nor VERSION" ."--version check failed")}my$version=eval "\$$class\::VERSION";if (defined$version){local $^W if $] <= 5.008;$version=version::vpp->new($version)}if (defined$req){unless (defined$version){require Carp;my$msg=$] < 5.006 ? "$class version $req required--this is only version " : "$class does not define \$$class\::VERSION" ."--version check failed";if ($ENV{VERSION_DEBUG}){Carp::confess($msg)}else {Carp::croak($msg)}}$req=version::vpp->new($req);if ($req > $version){require Carp;if ($req->is_qv){Carp::croak(sprintf ("%s version %s required--"."this is only version %s",$class,$req->normal,$version->normal))}else {Carp::croak(sprintf ("%s version %s required--"."this is only version %s",$class,$req->stringify,$version->stringify))}}}return defined$version ? $version->stringify : undef}1;
+      '}sub import {no strict 'refs';my ($class)=shift;unless ($class eq $CLASS){local $^W;*{$class.'::declare'}=\&{$CLASS.'::declare'};*{$class.'::qv'}=\&{$CLASS.'::qv'}}my%args;if (@_){map {$args{$_}=1}@_}else {%args=(qv=>1,'UNIVERSAL::VERSION'=>1,)}my$callpkg=caller();if (exists($args{declare})){*{$callpkg.'::declare'}=sub {return$class->declare(shift)}unless defined(&{$callpkg.'::declare'})}if (exists($args{qv})){*{$callpkg.'::qv'}=sub {return$class->qv(shift)}unless defined(&{$callpkg.'::qv'})}if (exists($args{'UNIVERSAL::VERSION'})){local $^W;*UNIVERSAL::VERSION =\&{$CLASS.'::_VERSION'}}if (exists($args{'VERSION'})){*{$callpkg.'::VERSION'}=\&{$CLASS.'::_VERSION'}}if (exists($args{'is_strict'})){*{$callpkg.'::is_strict'}=\&{$CLASS.'::is_strict'}unless defined(&{$callpkg.'::is_strict'})}if (exists($args{'is_lax'})){*{$callpkg.'::is_lax'}=\&{$CLASS.'::is_lax'}unless defined(&{$callpkg.'::is_lax'})}}my$VERSION_MAX=0x7FFFFFFF;use constant TRUE=>1;use constant FALSE=>0;sub isDIGIT {my ($char)=shift->thischar();return ($char =~ /\d/)}sub isALPHA {my ($char)=shift->thischar();return ($char =~ /[a-zA-Z]/)}sub isSPACE {my ($char)=shift->thischar();return ($char =~ /\s/)}sub BADVERSION {my ($s,$errstr,$error)=@_;if ($errstr){$$errstr=$error}return$s}sub prescan_version {my ($s,$strict,$errstr,$sqv,$ssaw_decimal,$swidth,$salpha)=@_;my$qv=defined$sqv ? $$sqv : FALSE;my$saw_decimal=defined$ssaw_decimal ? $$ssaw_decimal : 0;my$width=defined$swidth ? $$swidth : 3;my$alpha=defined$salpha ? $$salpha : FALSE;my$d=$s;if ($qv && isDIGIT($d)){goto dotted_decimal_version}if ($d eq 'v'){$d++;if (isDIGIT($d)){$qv=TRUE}else {return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}dotted_decimal_version: if ($strict && $d eq '0' && isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)")}while (isDIGIT($d)){$d++}if ($d eq '.'){$saw_decimal++;$d++}else {if ($strict){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}else {goto version_prescan_finish}}{my$i=0;my$j=0;while (isDIGIT($d)){$i++;while (isDIGIT($d)){$d++;$j++;if ($strict && $j > 3){return BADVERSION($s,$errstr,"Invalid version format (maximum 3 digits between decimals)")}}if ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)")}$d++;$alpha=TRUE}elsif ($d eq '.'){if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)")}$saw_decimal++;$d++}elsif (!isDIGIT($d)){last}$j=0}if ($strict && $i < 2){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)")}}}else {my$j=0;if ($strict){if ($d eq '.'){return BADVERSION($s,$errstr,"Invalid version format (0 before decimal required)")}if ($d eq '0' && isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)")}}if ($d eq '-'){return BADVERSION($s,$errstr,"Invalid version format (negative version number)")}while (isDIGIT($d)){$d++}if ($d eq '.'){$saw_decimal++;$d++}elsif (!$d || $d eq ';' || isSPACE($d)|| $d eq '}'){if ($d==$s){return BADVERSION($s,$errstr,"Invalid version format (version required)")}goto version_prescan_finish}elsif ($d==$s){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}elsif ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}elsif (isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (alpha without decimal)")}else {return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)")}}elsif ($d){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}if ($d &&!isDIGIT($d)&& ($strict ||!($d eq ';' || isSPACE($d)|| $d eq '}'))){return BADVERSION($s,$errstr,"Invalid version format (fractional part required)")}while (isDIGIT($d)){$d++;$j++;if ($d eq '.' && isDIGIT($d-1)){if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)")}if ($strict){return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions must begin with 'v')")}$d=$s;$qv=TRUE;goto dotted_decimal_version}if ($d eq '_'){if ($strict){return BADVERSION($s,$errstr,"Invalid version format (no underscores)")}if ($alpha){return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)")}if (!isDIGIT($d+1)){return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)")}$width=$j;$d++;$alpha=TRUE}}}version_prescan_finish: while (isSPACE($d)){$d++}if ($d &&!isDIGIT($d)&& (!($d eq ';' || $d eq '}'))){return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)")}if (defined$sqv){$$sqv=$qv}if (defined$swidth){$$swidth=$width}if (defined$ssaw_decimal){$$ssaw_decimal=$saw_decimal}if (defined$salpha){$$salpha=$alpha}return$d}sub scan_version {my ($s,$rv,$qv)=@_;my$start;my$pos;my$last;my$errstr;my$saw_decimal=0;my$width=3;my$alpha=FALSE;my$vinf=FALSE;my@av;$s=new charstar$s;while (isSPACE($s)){$s++}$last=prescan_version($s,FALSE,\$errstr,\$qv,\$saw_decimal,\$width,\$alpha);if ($errstr){if ($s ne 'undef'){require Carp;Carp::croak($errstr)}}$start=$s;if ($s eq 'v'){$s++}$pos=$s;if ($qv){$$rv->{qv}=$qv}if ($alpha){$$rv->{alpha}=$alpha}if (!$qv && $width < 3){$$rv->{width}=$width}while (isDIGIT($pos)){$pos++}if (!isALPHA($pos)){my$rev;for (;;){$rev=0;{my$end=$pos;my$mult=1;my$orev;if (!$qv && $s > $start && $saw_decimal==1){$mult *= 100;while ($s < $end){$orev=$rev;$rev += $s * $mult;$mult /= 10;if ((abs($orev)> abs($rev))|| (abs($rev)> $VERSION_MAX)){warn("Integer overflow in version %d",$VERSION_MAX);$s=$end - 1;$rev=$VERSION_MAX;$vinf=1}$s++;if ($s eq '_'){$s++}}}else {while (--$end >= $s){$orev=$rev;$rev += $end * $mult;$mult *= 10;if ((abs($orev)> abs($rev))|| (abs($rev)> $VERSION_MAX)){warn("Integer overflow in version");$end=$s - 1;$rev=$VERSION_MAX;$vinf=1}}}}push@av,$rev;if ($vinf){$s=$last;last}elsif ($pos eq '.'){$s=++$pos}elsif ($pos eq '_' && isDIGIT($pos+1)){$s=++$pos}elsif ($pos eq ',' && isDIGIT($pos+1)){$s=++$pos}elsif (isDIGIT($pos)){$s=$pos}else {$s=$pos;last}if ($qv){while (isDIGIT($pos)){$pos++}}else {my$digits=0;while ((isDIGIT($pos)|| $pos eq '_')&& $digits < 3){if ($pos ne '_'){$digits++}$pos++}}}}if ($qv){my$len=$#av;$len=2 - $len;while ($len-- > 0){push@av,0}}if ($vinf){$$rv->{original}="v.Inf";$$rv->{vinf}=1}elsif ($s > $start){$$rv->{original}=$start->currstr($s);if ($qv && $saw_decimal==1 && $start ne 'v'){$$rv->{original}='v' .$$rv->{original}}}else {$$rv->{original}='0';push(@av,0)}$$rv->{version}=\@av;if ($s eq 'undef'){$s += 5}return$s}sub new {my$class=shift;unless (defined$class or $#_ > 1){require Carp;Carp::croak('Usage: version::new(class, version)')}my$self=bless ({},ref ($class)|| $class);my$qv=FALSE;if ($#_==1){$qv=TRUE}my$value=pop;if (ref($value)&& eval('$value->isa("version")')){$self->{version}=[@{$value->{version}}];$self->{qv}=1 if$value->{qv};$self->{alpha}=1 if$value->{alpha};$self->{original}=''.$value->{original};return$self}if (not defined$value or $value =~ /^undef$/){push @{$self->{version}},0;$self->{original}="0";return ($self)}if (ref($value)=~ m/ARRAY|HASH/){require Carp;Carp::croak("Invalid version format (non-numeric data)")}$value=_un_vstring($value);if ($Config{d_setlocale}){use POSIX qw/locale_h/;use if$Config{d_setlocale},'locale';my$currlocale=setlocale(LC_ALL);if (localeconv()->{decimal_point}eq ','){$value =~ tr/,/./}}if ($value =~ /\d+.?\d*e[-+]?\d+/){$value=sprintf("%.9f",$value);$value =~ s/(0+)$//}my$s=scan_version($value,\$self,$qv);if ($s){warn("Version string '%s' contains invalid data; " ."ignoring: '%s'",$value,$s)}return ($self)}*parse=\&new;sub numify {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}my$width=$self->{width}|| 3;my$alpha=$self->{alpha}|| "";my$len=$#{$self->{version}};my$digit=$self->{version}[0];my$string=sprintf("%d.",$digit);for (my$i=1 ;$i < $len ;$i++ ){$digit=$self->{version}[$i];if ($width < 3){my$denom=10**(3-$width);my$quot=int($digit/$denom);my$rem=$digit - ($quot * $denom);$string .= sprintf("%0".$width."d_%d",$quot,$rem)}else {$string .= sprintf("%03d",$digit)}}if ($len > 0){$digit=$self->{version}[$len];if ($alpha && $width==3){$string .= "_"}$string .= sprintf("%0".$width."d",$digit)}else {$string .= sprintf("000")}return$string}sub normal {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}my$alpha=$self->{alpha}|| "";my$len=$#{$self->{version}};my$digit=$self->{version}[0];my$string=sprintf("v%d",$digit);for (my$i=1 ;$i < $len ;$i++ ){$digit=$self->{version}[$i];$string .= sprintf(".%d",$digit)}if ($len > 0){$digit=$self->{version}[$len];if ($alpha){$string .= sprintf("_%0d",$digit)}else {$string .= sprintf(".%0d",$digit)}}if ($len <= 2){for ($len=2 - $len;$len!=0;$len-- ){$string .= sprintf(".%0d",0)}}return$string}sub stringify {my ($self)=@_;unless (_verify($self)){require Carp;Carp::croak("Invalid version object")}return exists$self->{original}? $self->{original}: exists$self->{qv}? $self->normal : $self->numify}sub vcmp {require UNIVERSAL;my ($left,$right,$swap)=@_;my$class=ref($left);unless (UNIVERSAL::isa($right,$class)){$right=$class->new($right)}if ($swap){($left,$right)=($right,$left)}unless (_verify($left)){require Carp;Carp::croak("Invalid version object")}unless (_verify($right)){require Carp;Carp::croak("Invalid version format")}my$l=$#{$left->{version}};my$r=$#{$right->{version}};my$m=$l < $r ? $l : $r;my$lalpha=$left->is_alpha;my$ralpha=$right->is_alpha;my$retval=0;my$i=0;while ($i <= $m && $retval==0){$retval=$left->{version}[$i]<=> $right->{version}[$i];$i++}if ($retval==0 && $l==$r && $left->{version}[$m]==$right->{version}[$m]&& ($lalpha || $ralpha)){if ($lalpha &&!$ralpha){$retval=-1}elsif ($ralpha &&!$lalpha){$retval=+1}}if ($retval==0 && $l!=$r){if ($l < $r){while ($i <= $r && $retval==0){if ($right->{version}[$i]!=0){$retval=-1}$i++}}else {while ($i <= $l && $retval==0){if ($left->{version}[$i]!=0){$retval=+1}$i++}}}return$retval}sub vbool {my ($self)=@_;return vcmp($self,$self->new("0"),1)}sub vnoop {require Carp;Carp::croak("operation not supported with version object")}sub is_alpha {my ($self)=@_;return (exists$self->{alpha})}sub qv {my$value=shift;my$class=$CLASS;if (@_){$class=ref($value)|| $value;$value=shift}$value=_un_vstring($value);$value='v'.$value unless$value =~ /(^v|\d+\.\d+\.\d)/;my$obj=$CLASS->new($value);return bless$obj,$class}*declare=\&qv;sub is_qv {my ($self)=@_;return (exists$self->{qv})}sub _verify {my ($self)=@_;if (ref($self)&& eval {exists$self->{version}}&& ref($self->{version})eq 'ARRAY'){return 1}else {return 0}}sub _is_non_alphanumeric {my$s=shift;$s=new charstar$s;while ($s){return 0 if isSPACE($s);return 1 unless (isALPHA($s)|| isDIGIT($s)|| $s =~ /[.-]/);$s++}return 0}sub _un_vstring {my$value=shift;if (length($value)>= 3 && $value !~ /[._]/ && _is_non_alphanumeric($value)){my$tvalue;if ($] ge 5.008_001){$tvalue=_find_magic_vstring($value);$value=$tvalue if length$tvalue}elsif ($] ge 5.006_000){$tvalue=sprintf("v%vd",$value);if ($tvalue =~ /^v\d+(\.\d+){2,}$/){$value=$tvalue}}}return$value}sub _find_magic_vstring {my$value=shift;my$tvalue='';require B;my$sv=B::svref_2object(\$value);my$magic=ref($sv)eq 'B::PVMG' ? $sv->MAGIC : undef;while ($magic){if ($magic->TYPE eq 'V'){$tvalue=$magic->PTR;$tvalue =~ s/^v?(.+)$/v$1/;last}else {$magic=$magic->MOREMAGIC}}return$tvalue}sub _VERSION {my ($obj,$req)=@_;my$class=ref($obj)|| $obj;no strict 'refs';if (exists$INC{"$class.pm"}and not %{"$class\::"}and $] >= 5.008){require Carp;Carp::croak("$class defines neither package nor VERSION" ."--version check failed")}my$version=eval "\$$class\::VERSION";if (defined$version){local $^W if $] <= 5.008;$version=version::vpp->new($version)}if (defined$req){unless (defined$version){require Carp;my$msg=$] < 5.006 ? "$class version $req required--this is only version " : "$class does not define \$$class\::VERSION" ."--version check failed";if ($ENV{VERSION_DEBUG}){Carp::confess($msg)}else {Carp::croak($msg)}}$req=version::vpp->new($req);if ($req > $version){require Carp;if ($req->is_qv){Carp::croak(sprintf ("%s version %s required--"."this is only version %s",$class,$req->normal,$version->normal))}else {Carp::croak(sprintf ("%s version %s required--"."this is only version %s",$class,$req->stringify,$version->stringify))}}}return defined$version ? $version->stringify : undef}1;
 VERSION_VPP
 
 s/^  //mg for values %fatpacked;
 
-unshift @INC, sub {
-  if (my $fat = $fatpacked{$_[1]}) {
-    if ($] < 5.008) {
-      return sub {
-        return 0 unless length $fat;
-        $fat =~ s/^([^\n]*\n?)//;
-        $_ = $1;
-        return 1;
-      };
+my $class = 'FatPacked::'.(0+\%fatpacked);
+no strict 'refs';
+*{"${class}::files"} = sub { keys %{$_[0]} };
+
+if ($] < 5.008) {
+  *{"${class}::INC"} = sub {
+     if (my $fat = $_[0]{$_[1]}) {
+       return sub {
+         return 0 unless length $fat;
+         $fat =~ s/^([^\n]*\n?)//;
+         $_ = $1;
+         return 1;
+       };
+     }
+     return;
+  };
+}
+
+else {
+  *{"${class}::INC"} = sub {
+    if (my $fat = $_[0]{$_[1]}) {
+      open my $fh, '<', \$fat
+        or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
+      return $fh;
     }
-    open my $fh, '<', \$fat
-      or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
-    return $fh;
-  }
-  return
-};
+    return;
+  };
+}
 
-} # END OF FATPACK CODE
+unshift @INC, bless \%fatpacked, $class;
+  } # END OF FATPACK CODE
 
 
 
@@ -18,9 +18,9 @@ our $VERSION = "1.6928";
 BEGIN {
 my %fatpacked;
 
-$fatpacked{"App/cpanminus.pm"} = <<'APP_CPANMINUS';
+$fatpacked{"App/cpanminus.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS';
   package App::cpanminus;
-  our $VERSION = "1.7001";
+  our $VERSION = "1.7004";
   
   =encoding utf8
   
@@ -307,7 +307,7 @@ $fatpacked{"App/cpanminus.pm"} = <<'APP_CPANMINUS';
   1;
 APP_CPANMINUS
 
-$fatpacked{"App/cpanminus/CPANVersion.pm"} = <<'APP_CPANMINUS_CPANVERSION';
+$fatpacked{"App/cpanminus/CPANVersion.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_CPANVERSION';
   package App::cpanminus::CPANVersion;
   # copy of CPAN::Version since it's not core on older 5.8
   
@@ -440,7 +440,7 @@ $fatpacked{"App/cpanminus/CPANVersion.pm"} = <<'APP_CPANMINUS_CPANVERSION';
   __END__
 APP_CPANMINUS_CPANVERSION
 
-$fatpacked{"App/cpanminus/Dependency.pm"} = <<'APP_CPANMINUS_DEPENDENCY';
+$fatpacked{"App/cpanminus/Dependency.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_DEPENDENCY';
   package App::cpanminus::Dependency;
   use strict;
   use CPAN::Meta::Requirements;
@@ -493,7 +493,7 @@ $fatpacked{"App/cpanminus/Dependency.pm"} = <<'APP_CPANMINUS_DEPENDENCY';
   1;
 APP_CPANMINUS_DEPENDENCY
 
-$fatpacked{"App/cpanminus/ParsePM.pm"} = <<'APP_CPANMINUS_PARSEPM';
+$fatpacked{"App/cpanminus/ParsePM.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_PARSEPM';
   package App::cpanminus::ParsePM;
   # fork of Parse::PMFile, use JSON::PP instead of JSON
   
@@ -1037,7 +1037,7 @@ $fatpacked{"App/cpanminus/ParsePM.pm"} = <<'APP_CPANMINUS_PARSEPM';
   __END__
 APP_CPANMINUS_PARSEPM
 
-$fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
+$fatpacked{"App/cpanminus/script.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'APP_CPANMINUS_SCRIPT';
   package App::cpanminus::script;
   use strict;
   use Config;
@@ -1450,8 +1450,8 @@ $fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
               my $self = shift;
               my $temp_log = "$home/build.log." . time . ".$$";
               File::Copy::copy($log, $temp_log)
-                  && unlink($final_log)
-                  && rename($temp_log, $final_log);
+                  && unlink($final_log);
+              rename($temp_log, $final_log);
           }
       }
   
@@ -1923,7 +1923,8 @@ $fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
   
   sub local_lib_target {
       my($self, $root) = @_;
-      (grep { $_ ne '' } split /\Q$Config{path_sep}/, $root)[-1];
+      # local::lib 1.008025 changed the order of PERL_LOCAL_LIB_ROOT
+      (grep { $_ ne '' } split /\Q$Config{path_sep}/, $root)[0];
   }
   
   sub bootstrap_local_lib {
@@ -4096,7 +4097,7 @@ $fatpacked{"App/cpanminus/script.pm"} = <<'APP_CPANMINUS_SCRIPT';
   1;
 APP_CPANMINUS_SCRIPT
 
-$fatpacked{"CPAN/DistnameInfo.pm"} = <<'CPAN_DISTNAMEINFO';
+$fatpacked{"CPAN/DistnameInfo.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_DISTNAMEINFO';
   
   package CPAN::DistnameInfo;
   
@@ -4304,7 +4305,7 @@ $fatpacked{"CPAN/DistnameInfo.pm"} = <<'CPAN_DISTNAMEINFO';
   
 CPAN_DISTNAMEINFO
 
-$fatpacked{"CPAN/Meta.pm"} = <<'CPAN_META';
+$fatpacked{"CPAN/Meta.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META';
   use 5.006;
   use strict;
   use warnings;
@@ -5090,7 +5091,7 @@ $fatpacked{"CPAN/Meta.pm"} = <<'CPAN_META';
   
   =item *
   
-  Olivier Mengué <dolmen@cpan.org>
+  Olivier Mengué <dolmen@cpan.org>
   
   =item *
   
@@ -5108,7 +5109,7 @@ $fatpacked{"CPAN/Meta.pm"} = <<'CPAN_META';
   =cut
 CPAN_META
 
-$fatpacked{"CPAN/Meta/Check.pm"} = <<'CPAN_META_CHECK';
+$fatpacked{"CPAN/Meta/Check.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_CHECK';
   package CPAN::Meta::Check;
   {
     $CPAN::Meta::Check::VERSION = '0.007';
@@ -5249,7 +5250,7 @@ $fatpacked{"CPAN/Meta/Check.pm"} = <<'CPAN_META_CHECK';
   =cut
 CPAN_META_CHECK
 
-$fatpacked{"CPAN/Meta/Converter.pm"} = <<'CPAN_META_CONVERTER';
+$fatpacked{"CPAN/Meta/Converter.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_CONVERTER';
   use 5.006;
   use strict;
   use warnings;
@@ -6650,7 +6651,7 @@ $fatpacked{"CPAN/Meta/Converter.pm"} = <<'CPAN_META_CONVERTER';
   =cut
 CPAN_META_CONVERTER
 
-$fatpacked{"CPAN/Meta/Feature.pm"} = <<'CPAN_META_FEATURE';
+$fatpacked{"CPAN/Meta/Feature.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_FEATURE';
   use 5.006;
   use strict;
   use warnings;
@@ -6764,7 +6765,7 @@ $fatpacked{"CPAN/Meta/Feature.pm"} = <<'CPAN_META_FEATURE';
   =cut
 CPAN_META_FEATURE
 
-$fatpacked{"CPAN/Meta/History.pm"} = <<'CPAN_META_HISTORY';
+$fatpacked{"CPAN/Meta/History.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_HISTORY';
   # vi:tw=72
   use 5.006;
   use strict;
@@ -7082,7 +7083,7 @@ $fatpacked{"CPAN/Meta/History.pm"} = <<'CPAN_META_HISTORY';
   =cut
 CPAN_META_HISTORY
 
-$fatpacked{"CPAN/Meta/Prereqs.pm"} = <<'CPAN_META_PREREQS';
+$fatpacked{"CPAN/Meta/Prereqs.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_PREREQS';
   use 5.006;
   use strict;
   use warnings;
@@ -7357,7 +7358,7 @@ $fatpacked{"CPAN/Meta/Prereqs.pm"} = <<'CPAN_META_PREREQS';
   =cut
 CPAN_META_PREREQS
 
-$fatpacked{"CPAN/Meta/Requirements.pm"} = <<'CPAN_META_REQUIREMENTS';
+$fatpacked{"CPAN/Meta/Requirements.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_REQUIREMENTS';
   use strict;
   use warnings;
   package CPAN::Meta::Requirements;
@@ -8090,7 +8091,7 @@ $fatpacked{"CPAN/Meta/Requirements.pm"} = <<'CPAN_META_REQUIREMENTS';
   =cut
 CPAN_META_REQUIREMENTS
 
-$fatpacked{"CPAN/Meta/Spec.pm"} = <<'CPAN_META_SPEC';
+$fatpacked{"CPAN/Meta/Spec.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_SPEC';
   # XXX RULES FOR PATCHING THIS FILE XXX
   # Patches that fix typos or formatting are acceptable.  Patches
   # that change semantics are not acceptable without prior approval
@@ -9236,7 +9237,7 @@ $fatpacked{"CPAN/Meta/Spec.pm"} = <<'CPAN_META_SPEC';
   =cut
 CPAN_META_SPEC
 
-$fatpacked{"CPAN/Meta/Validator.pm"} = <<'CPAN_META_VALIDATOR';
+$fatpacked{"CPAN/Meta/Validator.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_VALIDATOR';
   use 5.006;
   use strict;
   use warnings;
@@ -10292,7 +10293,7 @@ $fatpacked{"CPAN/Meta/Validator.pm"} = <<'CPAN_META_VALIDATOR';
   =cut
 CPAN_META_VALIDATOR
 
-$fatpacked{"CPAN/Meta/YAML.pm"} = <<'CPAN_META_YAML';
+$fatpacked{"CPAN/Meta/YAML.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CPAN_META_YAML';
   package CPAN::Meta::YAML;
   {
     $CPAN::Meta::YAML::VERSION = '0.008';
@@ -11036,7 +11037,7 @@ $fatpacked{"CPAN/Meta/YAML.pm"} = <<'CPAN_META_YAML';
   
 CPAN_META_YAML
 
-$fatpacked{"Exporter.pm"} = <<'EXPORTER';
+$fatpacked{"Exporter.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER';
   package Exporter;
   
   require 5.006;
@@ -11630,7 +11631,7 @@ $fatpacked{"Exporter.pm"} = <<'EXPORTER';
   
 EXPORTER
 
-$fatpacked{"Exporter/Heavy.pm"} = <<'EXPORTER_HEAVY';
+$fatpacked{"Exporter/Heavy.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_HEAVY';
   package Exporter::Heavy;
   
   use strict;
@@ -11881,7 +11882,7 @@ $fatpacked{"Exporter/Heavy.pm"} = <<'EXPORTER_HEAVY';
   1;
 EXPORTER_HEAVY
 
-$fatpacked{"File/pushd.pm"} = <<'FILE_PUSHD';
+$fatpacked{"File/pushd.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'FILE_PUSHD';
   use strict;
   use warnings;
   package File::pushd;
@@ -12163,24 +12164,87 @@ $fatpacked{"File/pushd.pm"} = <<'FILE_PUSHD';
   =cut
 FILE_PUSHD
 
-$fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
+$fatpacked{"HTTP/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'HTTP_TINY';
   # vim: ts=4 sts=4 sw=4 et:
   package HTTP::Tiny;
   use strict;
   use warnings;
   # ABSTRACT: A small, simple, correct HTTP/1.1 client
-  our $VERSION = '0.034'; # VERSION
+  our $VERSION = '0.043'; # VERSION
   
   use Carp ();
   
+  # =method new
+  #
+  #     $http = HTTP::Tiny->new( %attributes );
+  #
+  # This constructor returns a new HTTP::Tiny object.  Valid attributes include:
+  #
+  # =for :list
+  # * C<agent>
+  # A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in a space character, the default user-agent string is appended.
+  # * C<cookie_jar>
+  # An instance of L<HTTP::CookieJar> or equivalent class that supports the C<add> and C<cookie_header> methods
+  # * C<default_headers>
+  # A hashref of default headers to apply to requests
+  # * C<local_address>
+  # The local IP address to bind to
+  # * C<keep_alive>
+  # Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
+  # * C<max_redirect>
+  # Maximum number of redirects allowed (defaults to 5)
+  # * C<max_size>
+  # Maximum response size (only when not using a data callback).  If defined, responses larger than this will return an exception.
+  # * C<http_proxy>
+  # URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
+  # * C<https_proxy>
+  # URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
+  # * C<proxy>
+  # URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
+  # * C<no_proxy>
+  # List of domain suffixes that should not be proxied.  Must be a comma-separated string or an array reference. (default is C<$ENV{no_proxy}>)
+  # * C<timeout>
+  # Request timeout in seconds (default is 60)
+  # * C<verify_SSL>
+  # A boolean that indicates whether to validate the SSL certificate of an C<https>
+  # connection (default is false)
+  # * C<SSL_options>
+  # A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
+  #
+  # Exceptions from C<max_size>, C<timeout> or other errors will result in a
+  # pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
+  # content field in the response will contain the text of the exception.
+  #
+  # The C<keep_alive> parameter enables a persistent connection, but only to a
+  # single destination scheme, host and port.  Also, if any connection-relevant
+  # attributes are modified, a persistent connection will be dropped.  If you want
+  # persistent connections across multiple destinations, use multiple HTTP::Tiny
+  # objects.
+  #
+  # See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
+  #
+  # =cut
   
   my @attributes;
   BEGIN {
-      @attributes = qw(cookie_jar default_headers local_address max_redirect max_size proxy no_proxy timeout SSL_options verify_SSL);
+      @attributes = qw(
+          cookie_jar default_headers http_proxy https_proxy keep_alive
+          local_address max_redirect max_size proxy no_proxy timeout
+          SSL_options verify_SSL
+      );
+      my %persist_ok = map {; $_ => 1 } qw(
+          cookie_jar default_headers max_redirect max_size
+      );
       no strict 'refs';
+      no warnings 'uninitialized';
       for my $accessor ( @attributes ) {
           *{$accessor} = sub {
-              @_ > 1 ? $_[0]->{$accessor} = $_[1] : $_[0]->{$accessor};
+              @_ > 1
+                  ? do {
+                      delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor};
+                      $_[0]->{$accessor} = $_[1]
+                  }
+                  : $_[0]->{$accessor};
           };
       }
   }
@@ -12200,6 +12264,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       my $self = {
           max_redirect => 5,
           timeout      => 60,
+          keep_alive   => 1,
           verify_SSL   => $args{verify_SSL} || $args{verify_ssl} || 0, # no verification by default
           no_proxy     => $ENV{no_proxy},
       };
@@ -12214,13 +12279,43 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
       $self->agent( exists $args{agent} ? $args{agent} : $class->_agent );
   
-      # Never override proxy argument as this breaks backwards compat.
-      if (!exists $self->{proxy} && (my $http_proxy = $ENV{http_proxy})) {
-          if ($http_proxy =~ m{\Ahttp://[^/?#:@]+:\d+/?\z}) {
-              $self->{proxy} = $http_proxy;
+      $self->_set_proxies;
+  
+      return $self;
+  }
+  
+  sub _set_proxies {
+      my ($self) = @_;
+  
+      if (! $self->{proxy} ) {
+          $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY};
+          if ( defined $self->{proxy} ) {
+              $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate
           }
           else {
-              Carp::croak(qq{Environment 'http_proxy' must be in format http://<host>:<port>/\n});
+              delete $self->{proxy};
+          }
+      }
+  
+      if (! $self->{http_proxy} ) {
+          $self->{http_proxy} = $ENV{http_proxy} || $self->{proxy};
+          if ( defined $self->{http_proxy} ) {
+              $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate
+              $self->{_has_proxy}{http} = 1;
+          }
+          else {
+              delete $self->{http_proxy};
+          }
+      }
+  
+      if (! $self->{https_proxy} ) {
+          $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || $self->{proxy};
+          if ( $self->{https_proxy} ) {
+              $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate
+              $self->{_has_proxy}{https} = 1;
+          }
+          else {
+              delete $self->{https_proxy};
           }
       }
   
@@ -12230,9 +12325,22 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
               (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : [];
       }
   
-      return $self;
+      return;
   }
   
+  # =method get|head|put|post|delete
+  #
+  #     $response = $http->get($url);
+  #     $response = $http->get($url, \%options);
+  #     $response = $http->head($url);
+  #
+  # These methods are shorthand for calling C<request()> for the given method.  The
+  # URL must have unsafe characters escaped and international domain names encoded.
+  # See C<request()> for valid options and a description of the response.
+  #
+  # The C<success> field of the response will be true if the status code is 2XX.
+  #
+  # =cut
   
   for my $sub_name ( qw/get head put post delete/ ) {
       my $req_method = uc $sub_name;
@@ -12247,6 +12355,25 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   HERE
   }
   
+  # =method post_form
+  #
+  #     $response = $http->post_form($url, $form_data);
+  #     $response = $http->post_form($url, $form_data, \%options);
+  #
+  # This method executes a C<POST> request and sends the key/value pairs from a
+  # form data hash or array reference to the given URL with a C<content-type> of
+  # C<application/x-www-form-urlencoded>.  If data is provided as an array
+  # reference, the order is preserved; if provided as a hash reference, the terms
+  # are sorted on key and value for consistency.  See documentation for the
+  # C<www_form_urlencode> method for details on the encoding.
+  #
+  # The URL must have unsafe characters escaped and international domain names
+  # encoded.  See C<request()> for valid options and a description of the response.
+  # Any C<content-type> header or content in the options hashref will be ignored.
+  #
+  # The C<success> field of the response will be true if the status code is 2XX.
+  #
+  # =cut
   
   sub post_form {
       my ($self, $url, $data, $args) = @_;
@@ -12270,6 +12397,28 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       );
   }
   
+  # =method mirror
+  #
+  #     $response = $http->mirror($url, $file, \%options)
+  #     if ( $response->{success} ) {
+  #         print "$file is up to date\n";
+  #     }
+  #
+  # Executes a C<GET> request for the URL and saves the response body to the file
+  # name provided.  The URL must have unsafe characters escaped and international
+  # domain names encoded.  If the file already exists, the request will include an
+  # C<If-Modified-Since> header with the modification timestamp of the file.  You
+  # may specify a different C<If-Modified-Since> header yourself in the C<<
+  # $options->{headers} >> hash.
+  #
+  # The C<success> field of the response will be true if the status code is 2XX
+  # or if the status code is 304 (unmodified).
+  #
+  # If the file was modified and the server response includes a properly
+  # formatted C<Last-Modified> header, the file modification time will
+  # be updated accordingly.
+  #
+  # =cut
   
   sub mirror {
       my ($self, $url, $file, $args) = @_;
@@ -12279,13 +12428,16 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
           $args->{headers}{'if-modified-since'} ||= $self->_http_date($mtime);
       }
       my $tempfile = $file . int(rand(2**31));
-      open my $fh, ">", $tempfile
-          or Carp::croak(qq/Error: Could not open temporary file $tempfile for downloading: $!\n/);
+  
+      require Fcntl;
+      sysopen my $fh, $tempfile, Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY()
+         or Carp::croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/);
       binmode $fh;
       $args->{data_callback} = sub { print {$fh} $_[0] };
       my $response = $self->request('GET', $url, $args);
       close $fh
-          or Carp::croak(qq/Error: Could not close temporary file $tempfile: $!\n/);
+          or Carp::croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/);
+  
       if ( $response->{success} ) {
           rename $tempfile, $file
               or Carp::croak(qq/Error replacing $file with $tempfile: $!\n/);
@@ -12299,6 +12451,86 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       return $response;
   }
   
+  # =method request
+  #
+  #     $response = $http->request($method, $url);
+  #     $response = $http->request($method, $url, \%options);
+  #
+  # Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
+  # 'PUT', etc.) on the given URL.  The URL must have unsafe characters escaped and
+  # international domain names encoded.
+  #
+  # If the URL includes a "user:password" stanza, they will be used for Basic-style
+  # authorization headers.  (Authorization headers will not be included in a
+  # redirected request.) For example:
+  #
+  #     $http->request('GET', 'http://Aladdin:open sesame@example.com/');
+  #
+  # If the "user:password" stanza contains reserved characters, they must
+  # be percent-escaped:
+  #
+  #     $http->request('GET', 'http://john%40example.com:password@example.com/');
+  #
+  # A hashref of options may be appended to modify the request.
+  #
+  # Valid options are:
+  #
+  # =for :list
+  # * C<headers>
+  # A hashref containing headers to include with the request.  If the value for
+  # a header is an array reference, the header will be output multiple times with
+  # each value in the array.  These headers over-write any default headers.
+  # * C<content>
+  # A scalar to include as the body of the request OR a code reference
+  # that will be called iteratively to produce the body of the request
+  # * C<trailer_callback>
+  # A code reference that will be called if it exists to provide a hashref
+  # of trailing headers (only used with chunked transfer-encoding)
+  # * C<data_callback>
+  # A code reference that will be called for each chunks of the response
+  # body received.
+  #
+  # If the C<content> option is a code reference, it will be called iteratively
+  # to provide the content body of the request.  It should return the empty
+  # string or undef when the iterator is exhausted.
+  #
+  # If the C<content> option is the empty string, no C<content-type> or
+  # C<content-length> headers will be generated.
+  #
+  # If the C<data_callback> option is provided, it will be called iteratively until
+  # the entire response body is received.  The first argument will be a string
+  # containing a chunk of the response body, the second argument will be the
+  # in-progress response hash reference, as described below.  (This allows
+  # customizing the action of the callback based on the C<status> or C<headers>
+  # received prior to the content body.)
+  #
+  # The C<request> method returns a hashref containing the response.  The hashref
+  # will have the following keys:
+  #
+  # =for :list
+  # * C<success>
+  # Boolean indicating whether the operation returned a 2XX status code
+  # * C<url>
+  # URL that provided the response. This is the URL of the request unless
+  # there were redirections, in which case it is the last URL queried
+  # in a redirection chain
+  # * C<status>
+  # The HTTP status code of the response
+  # * C<reason>
+  # The response phrase returned by the server
+  # * C<content>
+  # The body of the response.  If the response does not have any content
+  # or if a data callback is provided to consume the response body,
+  # this will be the empty string
+  # * C<headers>
+  # A hashref of header fields.  All header field names will be normalized
+  # to be lower case. If a header is repeated, the value will be an arrayref;
+  # it will otherwise be a scalar string containing the value
+  #
+  # On an exception during the execution of the request, the C<status> field will
+  # contain 599, and the C<content> field will contain the text of the exception.
+  #
+  # =cut
   
   my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/;
   
@@ -12316,7 +12548,14 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
               && $@ =~ m{^(?:Socket closed|Unexpected end)};
       }
   
-      if (my $e = "$@") {
+      if (my $e = $@) {
+          # maybe we got a response hash thrown from somewhere deep
+          if ( ref $e eq 'HASH' && exists $e->{status} ) {
+              return $e;
+          }
+  
+          # otherwise, stringify it
+          $e = "$e";
           $response = {
               url     => $url,
               success => q{},
@@ -12332,6 +12571,19 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       return $response;
   }
   
+  # =method www_form_urlencode
+  #
+  #     $params = $http->www_form_urlencode( $data );
+  #     $response = $http->get("http://example.com/query?$params");
+  #
+  # This method converts the key/value pairs from a data hash or array reference
+  # into a C<x-www-form-urlencoded> string.  The keys and values from the data
+  # reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is an
+  # array reference, the key will be repeated with each of the values of the array
+  # reference.  If data is provided as a hash reference, the key/value pairs in the
+  # resulting string will be sorted by key and value for consistent ordering.
+  #
+  # =cut
   
   sub www_form_urlencode {
       my ($self, $data) = @_;
@@ -12355,7 +12607,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
           }
       }
   
-      return join("&", sort @terms);
+      return join("&", (ref $data eq 'ARRAY') ? (@terms) : (sort @terms) );
   }
   
   #--------------------------------------------------------------------------#
@@ -12381,27 +12633,23 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       my $request = {
           method    => $method,
           scheme    => $scheme,
+          host      => $host,
           host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"),
           uri       => $path_query,
           headers   => {},
       };
   
-      my $handle  = HTTP::Tiny::Handle->new(
-          timeout         => $self->{timeout},
-          SSL_options     => $self->{SSL_options},
-          verify_SSL      => $self->{verify_SSL},
-          local_address   => $self->{local_address},
-      );
-  
-      if ($self->{proxy} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) {
-          $request->{uri} = "$scheme://$request->{host_port}$path_query";
-          die(qq/HTTPS via proxy is not supported\n/)
-              if $request->{scheme} eq 'https';
-          $handle->connect(($self->_split_url($self->{proxy}))[0..2]);
-      }
-      else {
-          $handle->connect($scheme, $host, $port);
+      # We remove the cached handle so it is not reused in the case of redirect.
+      # If all is well, it will be recached at the end of _request.  We only
+      # reuse for the same scheme, host and port
+      my $handle = delete $self->{handle};
+      if ( $handle ) {
+          unless ( $handle->can_reuse( $scheme, $host, $port ) ) {
+              $handle->close;
+              undef $handle;
+          }
       }
+      $handle ||= $self->_open_handle( $request, $scheme, $host, $port );
   
       $self->_prepare_headers_and_cb($request, $args, $url, $auth);
       $handle->write_request($request);
@@ -12417,20 +12665,140 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
           return $self->_request(@redir_args, $args);
       }
   
+      my $known_message_length;
       if ($method eq 'HEAD' || $response->{status} =~ /^[23]04/) {
           # response has no message body
+          $known_message_length = 1;
       }
       else {
           my $data_cb = $self->_prepare_data_cb($response, $args);
-          $handle->read_body($data_cb, $response);
+          $known_message_length = $handle->read_body($data_cb, $response);
+      }
+  
+      if ( $self->{keep_alive}
+          && $known_message_length
+          && $response->{protocol} eq 'HTTP/1.1'
+          && ($response->{headers}{connection} || '') ne 'close'
+      ) {
+          $self->{handle} = $handle;
+      }
+      else {
+          $handle->close;
       }
   
-      $handle->close;
-      $response->{success} = substr($response->{status},0,1) eq '2';
+      $response->{success} = substr( $response->{status}, 0, 1 ) eq '2';
       $response->{url} = $url;
       return $response;
   }
   
+  sub _open_handle {
+      my ($self, $request, $scheme, $host, $port) = @_;
+  
+      my $handle  = HTTP::Tiny::Handle->new(
+          timeout         => $self->{timeout},
+          SSL_options     => $self->{SSL_options},
+          verify_SSL      => $self->{verify_SSL},
+          local_address   => $self->{local_address},
+          keep_alive      => $self->{keep_alive}
+      );
+  
+      if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) {
+          return $self->_proxy_connect( $request, $handle );
+      }
+      else {
+          return $handle->connect($scheme, $host, $port);
+      }
+  }
+  
+  sub _proxy_connect {
+      my ($self, $request, $handle) = @_;
+  
+      my @proxy_vars;
+      if ( $request->{scheme} eq 'https' ) {
+          Carp::croak(qq{No https_proxy defined}) unless $self->{https_proxy};
+          @proxy_vars = $self->_split_proxy( https_proxy => $self->{https_proxy} );
+          if ( $proxy_vars[0] eq 'https' ) {
+              Carp::croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}});
+          }
+      }
+      else {
+          Carp::croak(qq{No http_proxy defined}) unless $self->{http_proxy};
+          @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} );
+      }
+  
+      my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars;
+  
+      if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) {
+          $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth );
+      }
+  
+      $handle->connect($p_scheme, $p_host, $p_port);
+  
+      if ($request->{scheme} eq 'https') {
+          $self->_create_proxy_tunnel( $request, $handle );
+      }
+      else {
+          # non-tunneled proxy requires absolute URI
+          $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}";
+      }
+  
+      return $handle;
+  }
+  
+  sub _split_proxy {
+      my ($self, $type, $proxy) = @_;
+  
+      my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) };
+  
+      unless(
+          defined($scheme) && length($scheme) && length($host) && length($port)
+          && $path_query eq '/'
+      ) {
+          Carp::croak(qq{$type URL must be in format http[s]://[auth@]<host>:<port>/\n});
+      }
+  
+      return ($scheme, $host, $port, $auth);
+  }
+  
+  sub _create_proxy_tunnel {
+      my ($self, $request, $handle) = @_;
+  
+      $handle->_assert_ssl;
+  
+      my $agent = exists($request->{headers}{'user-agent'})
+          ? $request->{headers}{'user-agent'} : $self->{agent};
+  
+      my $connect_request = {
+          method    => 'CONNECT',
+          uri       => $request->{host_port},
+          headers   => {
+              host => $request->{host_port},
+              'user-agent' => $agent,
+          }
+      };
+  
+      if ( $request->{headers}{'proxy-authorization'} ) {
+          $connect_request->{headers}{'proxy-authorization'} =
+              delete $request->{headers}{'proxy-authorization'};
+      }
+  
+      $handle->write_request($connect_request);
+      my $response;
+      do { $response = $handle->read_response_header }
+          until (substr($response->{status},0,1) ne '1');
+  
+      # if CONNECT failed, throw the response so it will be
+      # returned from the original request() method;
+      unless (substr($response->{status},0,1) eq '2') {
+          die $response;
+      }
+  
+      # tunnel established, so start SSL handshake
+      $handle->start_ssl( $request->{host} );
+  
+      return;
+  }
+  
   sub _prepare_headers_and_cb {
       my ($self, $request, $args, $url, $auth) = @_;
   
@@ -12441,8 +12809,9 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
           }
       }
       $request->{headers}{'host'}         = $request->{host_port};
-      $request->{headers}{'connection'}   = "close";
       $request->{headers}{'user-agent'} ||= $self->{agent};
+      $request->{headers}{'connection'}   = "close"
+          unless $self->{keep_alive};
   
       if ( defined $args->{content} ) {
           if (ref $args->{content} eq 'CODE') {
@@ -12475,15 +12844,21 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       }
   
       # if we have Basic auth parameters, add them
-      if ( length $auth && ! defined $request->{headers}{authentication} ) {
-          require MIME::Base64;
-          $request->{headers}{authorization} =
-              "Basic " . MIME::Base64::encode_base64($auth, "");
+      if ( length $auth && ! defined $request->{headers}{authorization} ) {
+          $self->_add_basic_auth_header( $request, 'authorization' => $auth );
       }
   
       return;
   }
   
+  sub _add_basic_auth_header {
+      my ($self, $request, $header, $auth) = @_;
+      require MIME::Base64;
+      $request->{headers}{$header} =
+          "Basic " . MIME::Base64::encode_base64($auth, "");
+      return;
+  }
+  
   sub _prepare_data_cb {
       my ($self, $response, $args) = @_;
       my $data_cb = $args->{data_callback};
@@ -12559,6 +12934,8 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       $authority = (length($authority)) ? $authority : 'localhost';
       if ( $authority =~ /@/ ) {
           ($auth,$host) = $authority =~ m/\A([^@]*)@(.*)\z/;   # user:pass@host
+          # userinfo might be percent escaped, so recover real auth info
+          $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
       }
       else {
           $host = $authority;
@@ -12634,6 +13011,14 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   use Errno      qw[EINTR EPIPE];
   use IO::Socket qw[SOCK_STREAM];
   
+  # PERL_HTTP_TINY_IPV4_ONLY is a private environment variable to force old
+  # behavior if someone is unable to boostrap CPAN from a new perl install; it is
+  # not intended for general, per-client use and may be removed in the future
+  my $SOCKET_CLASS =
+      $ENV{PERL_HTTP_TINY_IPV4_ONLY} ? 'IO::Socket::INET' :
+      eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.25) } ? 'IO::Socket::IP' :
+      'IO::Socket::INET';
+  
   sub BUFSIZE () { 32768 } ## no critic
   
   my $Printable = sub {
@@ -12665,50 +13050,61 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       my ($self, $scheme, $host, $port) = @_;
   
       if ( $scheme eq 'https' ) {
-          # Need IO::Socket::SSL 1.42 for SSL_create_ctx_callback
-          die(qq/IO::Socket::SSL 1.42 must be installed for https support\n/)
-              unless eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.42)};
-          # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY
-          die(qq/Net::SSLeay 1.49 must be installed for https support\n/)
-              unless eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)};
+          $self->_assert_ssl;
       }
       elsif ( $scheme ne 'http' ) {
         die(qq/Unsupported URL scheme '$scheme'\n/);
       }
-      $self->{fh} = 'IO::Socket::INET'->new(
+      $self->{fh} = $SOCKET_CLASS->new(
           PeerHost  => $host,
           PeerPort  => $port,
           $self->{local_address} ?
               ( LocalAddr => $self->{local_address} ) : (),
           Proto     => 'tcp',
           Type      => SOCK_STREAM,
-          Timeout   => $self->{timeout}
+          Timeout   => $self->{timeout},
+          KeepAlive => !!$self->{keep_alive}
       ) or die(qq/Could not connect to '$host:$port': $@\n/);
   
       binmode($self->{fh})
         or die(qq/Could not binmode() socket: '$!'\n/);
   
-      if ( $scheme eq 'https') {
-          my $ssl_args = $self->_ssl_args($host);
-          IO::Socket::SSL->start_SSL(
-              $self->{fh},
-              %$ssl_args,
-              SSL_create_ctx_callback => sub {
-                  my $ctx = shift;
-                  Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY());
-              },
-          );
+      $self->start_ssl($host) if $scheme eq 'https';
+  
+      $self->{scheme} = $scheme;
+      $self->{host} = $host;
+      $self->{port} = $port;
   
-          unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
+      return $self;
+  }
+  
+  sub start_ssl {
+      my ($self, $host) = @_;
+  
+      # As this might be used via CONNECT after an SSL session
+      # to a proxy, we shut down any existing SSL before attempting
+      # the handshake
+      if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
+          unless ( $self->{fh}->stop_SSL ) {
               my $ssl_err = IO::Socket::SSL->errstr;
-              die(qq/SSL connection failed for $host: $ssl_err\n/);
+              die(qq/Error halting prior SSL connection: $ssl_err/);
           }
       }
   
-      $self->{host} = $host;
-      $self->{port} = $port;
+      my $ssl_args = $self->_ssl_args($host);
+      IO::Socket::SSL->start_SSL(
+          $self->{fh},
+          %$ssl_args,
+          SSL_create_ctx_callback => sub {
+              my $ctx = shift;
+              Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY());
+          },
+      );
   
-      return $self;
+      unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
+          my $ssl_err = IO::Socket::SSL->errstr;
+          die(qq/SSL connection failed for $host: $ssl_err\n/);
+      }
   }
   
   sub close {
@@ -12884,11 +13280,13 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       'x-xss-protection' => 'X-XSS-Protection',
   );
   
+  # to avoid multiple small writes and hence nagle, you can pass the method line or anything else to
+  # combine writes.
   sub write_header_lines {
-      (@_ == 2 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers)/ . "\n");
-      my($self, $headers) = @_;
+      (@_ == 2 || @_ == 3 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers[,prefix])/ . "\n");
+      my($self, $headers, $prefix_data) = @_;
   
-      my $buf = '';
+      my $buf = (defined $prefix_data ? $prefix_data : '');
       while (my ($k, $v) = each %$headers) {
           my $field_name = lc $k;
           if (exists $HeaderCase{$field_name}) {
@@ -12910,17 +13308,17 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       return $self->write($buf);
   }
   
+  # return value indicates whether message length was defined; this is generally
+  # true unless there was no content-length header and we just read until EOF.
+  # Other message length errors are thrown as exceptions
   sub read_body {
       @_ == 3 || die(q/Usage: $handle->read_body(callback, response)/ . "\n");
       my ($self, $cb, $response) = @_;
       my $te = $response->{headers}{'transfer-encoding'} || '';
-      if ( grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ) {
-          $self->read_chunked_body($cb, $response);
-      }
-      else {
-          $self->read_content_body($cb, $response);
-      }
-      return;
+      my $chunked = grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ;
+      return $chunked
+          ? $self->read_chunked_body($cb, $response)
+          : $self->read_content_body($cb, $response);
   }
   
   sub write_body {
@@ -12946,11 +13344,11 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
               $cb->($self->read($read, 0), $response);
               $len -= $read;
           }
+          return length($self->{rbuf}) == 0;
       }
-      else {
-          my $chunk;
-          $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) );
-      }
+  
+      my $chunk;
+      $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) );
   
       return;
   }
@@ -12999,7 +13397,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
             or die(qq/Malformed chunk: missing CRLF after chunk data\n/);
       }
       $self->read_header_lines($response->{headers});
-      return;
+      return 1;
   }
   
   sub write_chunked_body {
@@ -13048,10 +13446,10 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
           unless $version =~ /0*1\.0*[01]/;
   
       return {
-          status   => $status,
-          reason   => $reason,
-          headers  => $self->read_header_lines,
-          protocol => $protocol,
+          status       => $status,
+          reason       => $reason,
+          headers      => $self->read_header_lines,
+          protocol     => $protocol,
       };
   }
   
@@ -13059,8 +13457,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       @_ == 4 || die(q/Usage: $handle->write_request_header(method, request_uri, headers)/ . "\n");
       my ($self, $method, $request_uri, $headers) = @_;
   
-      return $self->write("$method $request_uri HTTP/1.1\x0D\x0A")
-           + $self->write_header_lines($headers);
+      return $self->write_header_lines($headers, "$method $request_uri HTTP/1.1\x0D\x0A");
   }
   
   sub _do_timeout {
@@ -13097,6 +13494,9 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   sub can_read {
       @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n");
       my $self = shift;
+      if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
+          return 1 if $self->{fh}->pending;
+      }
       return $self->_do_timeout('read', @_)
   }
   
@@ -13106,6 +13506,27 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       return $self->_do_timeout('write', @_)
   }
   
+  sub _assert_ssl {
+      # Need IO::Socket::SSL 1.42 for SSL_create_ctx_callback
+      die(qq/IO::Socket::SSL 1.42 must be installed for https support\n/)
+          unless eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.42)};
+      # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY
+      die(qq/Net::SSLeay 1.49 must be installed for https support\n/)
+          unless eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)};
+  }
+  
+  sub can_reuse {
+      my ($self,$scheme,$host,$port) = @_;
+      return 0 if
+           length($self->{rbuf})
+          || $scheme ne $self->{scheme}
+          || $host ne $self->{host}
+          || $port ne $self->{port}
+          || eval { $self->can_read(0) }
+          || $@ ;
+          return 1;
+  }
+  
   # Try to find a CA bundle to validate the SSL cert,
   # prefer Mozilla::CA or fallback to a system file
   sub _find_CA_file {
@@ -13134,7 +13555,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
       my ($self, $host) = @_;
   
       my %ssl_args;
-      
+  
       # This test reimplements IO::Socket::SSL::can_client_sni(), which wasn't
       # added until IO::Socket::SSL 1.84
       if ( Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000 ) {
@@ -13166,7 +13587,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =pod
   
-  =encoding utf-8
+  =encoding UTF-8
   
   =head1 NAME
   
@@ -13174,7 +13595,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =head1 VERSION
   
-  version 0.034
+  version 0.043
   
   =head1 SYNOPSIS
   
@@ -13196,12 +13617,16 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =head1 DESCRIPTION
   
-  This is a very simple HTTP/1.1 client, designed for doing simple GET
+  This is a very simple HTTP/1.1 client, designed for doing simple
   requests without the overhead of a large framework like L<LWP::UserAgent>.
   
   It is more correct and more complete than L<HTTP::Lite>.  It supports
-  proxies (currently only non-authenticating ones) and redirection.  It
-  also correctly resumes after EINTR.
+  proxies and redirection.  It also correctly resumes after EINTR.
+  
+  If L<IO::Socket::IP> 0.25 or later is installed, HTTP::Tiny will use it instead
+  of L<IO::Socket::INET> for transparent support for both IPv4 and IPv6.
+  
+  Cookie support requires L<HTTP::CookieJar> or an equivalent class.
   
   =head1 METHODS
   
@@ -13239,6 +13664,12 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
+  C<keep_alive>
+  
+  Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
+  
+  =item *
+  
   C<max_redirect>
   
   Maximum number of redirects allowed (defaults to 5)
@@ -13247,14 +13678,25 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   C<max_size>
   
-  Maximum response size (only when not using a data callback).  If defined,
-  responses larger than this will return an exception.
+  Maximum response size (only when not using a data callback).  If defined, responses larger than this will return an exception.
+  
+  =item *
+  
+  C<http_proxy>
+  
+  URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
+  
+  =item *
+  
+  C<https_proxy>
+  
+  URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
   
   =item *
   
   C<proxy>
   
-  URL of a proxy server to use (default is C<$ENV{http_proxy}> if set)
+  URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
   
   =item *
   
@@ -13287,6 +13729,12 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
   content field in the response will contain the text of the exception.
   
+  The C<keep_alive> parameter enables a persistent connection, but only to a
+  single destination scheme, host and port.  Also, if any connection-relevant
+  attributes are modified, a persistent connection will be dropped.  If you want
+  persistent connections across multiple destinations, use multiple HTTP::Tiny
+  objects.
+  
   See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
   
   =head2 get|head|put|post|delete
@@ -13308,7 +13756,9 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   This method executes a C<POST> request and sends the key/value pairs from a
   form data hash or array reference to the given URL with a C<content-type> of
-  C<application/x-www-form-urlencoded>.  See documentation for the
+  C<application/x-www-form-urlencoded>.  If data is provided as an array
+  reference, the order is preserved; if provided as a hash reference, the terms
+  are sorted on key and value for consistency.  See documentation for the
   C<www_form_urlencode> method for details on the encoding.
   
   The URL must have unsafe characters escaped and international domain names
@@ -13353,6 +13803,11 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
       $http->request('GET', 'http://Aladdin:open sesame@example.com/');
   
+  If the "user:password" stanza contains reserved characters, they must
+  be percent-escaped:
+  
+      $http->request('GET', 'http://john%40example.com:password@example.com/');
+  
   A hashref of options may be appended to modify the request.
   
   Valid options are:
@@ -13465,28 +13920,32 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   into a C<x-www-form-urlencoded> string.  The keys and values from the data
   reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is an
   array reference, the key will be repeated with each of the values of the array
-  reference.  The key/value pairs in the resulting string will be sorted by key
-  and value.
+  reference.  If data is provided as a hash reference, the key/value pairs in the
+  resulting string will be sorted by key and value for consistent ordering.
   
-  =for Pod::Coverage agent
+  =for Pod::Coverage SSL_options
+  agent
   cookie_jar
   default_headers
+  http_proxy
+  https_proxy
+  keep_alive
   local_address
   max_redirect
   max_size
-  proxy
   no_proxy
+  proxy
   timeout
   verify_SSL
-  SSL_options
   
   =head1 SSL SUPPORT
   
   Direct C<https> connections are supported only if L<IO::Socket::SSL> 1.56 or
   greater and L<Net::SSLeay> 1.49 or greater are installed. An exception will be
   thrown if a new enough versions of these modules not installed or if the SSL
-  encryption fails. There is no support for C<https> connections via proxy (i.e.
-  RFC 2817).
+  encryption fails. An C<https> connection may be made via an C<http> proxy that
+  supports the CONNECT command (i.e. RFC 2817).  You may not proxy C<https> via
+  a proxy that itself requires C<https> to communicate.
   
   SSL provides two distinct capabilities:
   
@@ -13563,6 +14022,43 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   cipher used for the SSL connection. See L<IO::Socket::SSL> documentation for
   details.
   
+  =head1 PROXY SUPPORT
+  
+  HTTP::Tiny can proxy both C<http> and C<https> requests.  Only Basic proxy
+  authorization is supported and it must be provided as part of the proxy URL:
+  C<http://user:pass@proxy.example.com/>.
+  
+  HTTP::Tiny supports the following proxy environment variables:
+  
+  =over 4
+  
+  =item *
+  
+  http_proxy
+  
+  =item *
+  
+  https_proxy or HTTPS_PROXY
+  
+  =item *
+  
+  all_proxy or ALL_PROXY
+  
+  =back
+  
+  Tunnelling C<https> over an C<http> proxy using the CONNECT method is
+  supported.  If your proxy uses C<https> itself, you can not tunnel C<https>
+  over it.
+  
+  Be warned that proxying an C<https> connection opens you to the risk of a
+  man-in-the-middle attack by the proxy server.
+  
+  The C<no_proxy> environment variable is supported in the format of a
+  comma-separated list of domain extensions proxy should not be used for.
+  
+  Proxy arguments passed to C<new> will override their corresponding
+  environment variables.
+  
   =head1 LIMITATIONS
   
   HTTP::Tiny is I<conditionally compliant> with the
@@ -13596,28 +14092,6 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
-  Persistent connections are not supported.  The C<Connection> header will
-  always be set to C<close>.
-  
-  =item *
-  
-  Cookie support requires L<HTTP::CookieJar> or an equivalent class.
-  
-  =item *
-  
-  Only the C<http_proxy> environment variable is supported in the format
-  C<http://HOST:PORT/>.  If a C<proxy> argument is passed to C<new> (including
-  undef), then the C<http_proxy> environment variable is ignored.
-  
-  =item *
-  
-  C<no_proxy> environment variable is supported in the format comma-separated
-  list of domain extensions proxy should not be used for.  If a C<no_proxy>
-  argument is passed to C<new>, then the C<no_proxy> environment variable is
-  ignored.
-  
-  =item *
-  
   There is no provision for delaying a request body using an C<Expect> header.
   Unexpected C<1XX> responses are silently ignored as per the specification.
   
@@ -13629,18 +14103,22 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   There is no support for a Request-URI of '*' for the 'OPTIONS' request.
   
-  =item *
-  
-  There is no support for IPv6 of any kind.
-  
   =back
   
+  Despite the limitations listed above, HTTP::Tiny is considered
+  feature-complete.  New feature requests should be directed to
+  L<HTTP::Tiny::UA>.
+  
   =head1 SEE ALSO
   
   =over 4
   
   =item *
   
+  L<HTTP::Tiny::UA> - Higher level UA features for HTTP::Tiny
+  
+  =item *
+  
   L<HTTP::Thin> - HTTP::Tiny wrapper with L<HTTP::Request>/L<HTTP::Response> compatibility
   
   =item *
@@ -13649,6 +14127,10 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
+  L<IO::Socket::IP> - Required for IPv6 support
+  
+  =item *
+  
   L<IO::Socket::SSL> - Required for SSL support
   
   =item *
@@ -13682,7 +14164,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   L<https://github.com/chansen/p5-http-tiny>
   
-    git clone git://github.com/chansen/p5-http-tiny.git
+    git clone https://github.com/chansen/p5-http-tiny.git
   
   =head1 AUTHORS
   
@@ -13728,6 +14210,10 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
+  Clinton Gormley <clint@traveljury.com>
+  
+  =item *
+  
   Craig Berry <cberry@cpan.org>
   
   =item *
@@ -13748,6 +14234,10 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
+  Martin J. Evans <mjegh@ntlworld.com>
+  
+  =item *
+  
   Martin-Louis Bright <mlbright@gmail.com>
   
   =item *
@@ -13756,6 +14246,10 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =item *
   
+  Petr Písař <ppisar@redhat.com>
+  
+  =item *
+  
   Serguei Trouchelle <stro@cpan.org>
   
   =item *
@@ -13770,7 +14264,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   
   =head1 COPYRIGHT AND LICENSE
   
-  This software is copyright (c) 2013 by Christian Hansen.
+  This software is copyright (c) 2014 by Christian Hansen.
   
   This is free software; you can redistribute it and/or modify it under
   the same terms as the Perl 5 programming language system itself.
@@ -13778,7 +14272,7 @@ $fatpacked{"HTTP/Tiny.pm"} = <<'HTTP_TINY';
   =cut
 HTTP_TINY
 
-$fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
+$fatpacked{"JSON/PP.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'JSON_PP';
   package JSON::PP;
   
   # JSON-2.0
@@ -13792,7 +14286,7 @@ $fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
   use B ();
   #use Devel::Peek;
   
-  $JSON::PP::VERSION = '2.27202';
+  $JSON::PP::VERSION = '2.27203';
   
   @JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json);
   
@@ -15345,7 +15839,7 @@ $fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
       $self->{incr_text} = substr( $self->{incr_text}, $p );
       $self->{incr_p} = 0;
   
-      return $obj or '';
+      return $obj || '';
   }
   
   
@@ -16580,7 +17074,7 @@ $fatpacked{"JSON/PP.pm"} = <<'JSON_PP';
   =cut
 JSON_PP
 
-$fatpacked{"JSON/PP/Boolean.pm"} = <<'JSON_PP_BOOLEAN';
+$fatpacked{"JSON/PP/Boolean.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'JSON_PP_BOOLEAN';
   =head1 NAME
   
   JSON::PP::Boolean - dummy module providing JSON::PP::Boolean
@@ -16609,7 +17103,7 @@ $fatpacked{"JSON/PP/Boolean.pm"} = <<'JSON_PP_BOOLEAN';
   
 JSON_PP_BOOLEAN
 
-$fatpacked{"Module/CPANfile.pm"} = <<'MODULE_CPANFILE';
+$fatpacked{"Module/CPANfile.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE';
   package Module::CPANfile;
   use strict;
   use warnings;
@@ -16905,7 +17399,7 @@ $fatpacked{"Module/CPANfile.pm"} = <<'MODULE_CPANFILE';
   =cut
 MODULE_CPANFILE
 
-$fatpacked{"Module/CPANfile/Environment.pm"} = <<'MODULE_CPANFILE_ENVIRONMENT';
+$fatpacked{"Module/CPANfile/Environment.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE_ENVIRONMENT';
   package Module::CPANfile::Environment;
   use strict;
   use warnings;
@@ -16972,7 +17466,7 @@ $fatpacked{"Module/CPANfile/Environment.pm"} = <<'MODULE_CPANFILE_ENVIRONMENT';
   
 MODULE_CPANFILE_ENVIRONMENT
 
-$fatpacked{"Module/CPANfile/Result.pm"} = <<'MODULE_CPANFILE_RESULT';
+$fatpacked{"Module/CPANfile/Result.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_CPANFILE_RESULT';
   package Module::CPANfile::Result;
   use strict;
   
@@ -17068,7 +17562,7 @@ $fatpacked{"Module/CPANfile/Result.pm"} = <<'MODULE_CPANFILE_RESULT';
   1;
 MODULE_CPANFILE_RESULT
 
-$fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
+$fatpacked{"Module/Metadata.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_METADATA';
   # -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*-
   # vim:ts=8:sw=2:et:sta:sts=2
   package Module::Metadata;
@@ -17081,8 +17575,9 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
   # parrot future to look at other types of modules).
   
   use strict;
-  use vars qw($VERSION);
-  $VERSION = '1.000016';
+  use warnings;
+  
+  our $VERSION = '1.000019';
   $VERSION = eval $VERSION;
   
   use Carp qw/croak/;
@@ -17143,7 +17638,7 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
     ([\$*])         # sigil - $ or *
     (
       (             # optional leading package name
-        (?:::|\')?  # possibly starting like just :: (Ì  la $::VERSION)
+        (?:::|\')?  # possibly starting like just :: (a la $::VERSION)
         (?:\w+(?:::|\'))*  # Foo::Bar:: ...
       )?
       VERSION
@@ -17720,10 +18215,11 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
     # compiletime/runtime issues with local()
     my $vsub;
     $pn++; # everybody gets their own package
-    my $eval = qq{BEGIN { q#  Hide from _packages_inside()
+    my $eval = qq{BEGIN { my \$dummy = q#  Hide from _packages_inside()
       #; package Module::Metadata::_version::p$pn;
       use version;
       no strict;
+      no warnings;
   
         \$vsub = sub {
           local $sigil$var;
@@ -17733,6 +18229,8 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
         };
     }};
   
+    $eval = $1 if $eval =~ m{^(.+)}s;
+  
     local $^W;
     # Try to get the $VERSION
     eval $eval;
@@ -18083,7 +18581,7 @@ $fatpacked{"Module/Metadata.pm"} = <<'MODULE_METADATA';
   
 MODULE_METADATA
 
-$fatpacked{"Parse/CPAN/Meta.pm"} = <<'PARSE_CPAN_META';
+$fatpacked{"Parse/CPAN/Meta.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PARSE_CPAN_META';
   use strict;
   package Parse::CPAN::Meta;
   # ABSTRACT: Parse META.yml and META.json CPAN metadata files
@@ -18401,7 +18899,7 @@ $fatpacked{"Parse/CPAN/Meta.pm"} = <<'PARSE_CPAN_META';
   
   =item *
   
-  Steffen Müller <smueller@cpan.org>
+  Steffen Müller <smueller@cpan.org>
   
   =back
   
@@ -18415,7 +18913,7 @@ $fatpacked{"Parse/CPAN/Meta.pm"} = <<'PARSE_CPAN_META';
   =cut
 PARSE_CPAN_META
 
-$fatpacked{"String/ShellQuote.pm"} = <<'STRING_SHELLQUOTE';
+$fatpacked{"String/ShellQuote.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'STRING_SHELLQUOTE';
   # $Id: ShellQuote.pm,v 1.11 2010-06-11 20:08:57 roderick Exp $
   #
   # Copyright (c) 1997 Roderick Schertler.  All rights reserved.  This
@@ -18614,7 +19112,7 @@ $fatpacked{"String/ShellQuote.pm"} = <<'STRING_SHELLQUOTE';
   =cut
 STRING_SHELLQUOTE
 
-$fatpacked{"aliased.pm"} = <<'ALIASED';
+$fatpacked{"aliased.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'ALIASED';
   package aliased;
   
   our $VERSION = '0.31';
@@ -18946,7 +19444,7 @@ $fatpacked{"aliased.pm"} = <<'ALIASED';
   =cut
 ALIASED
 
-$fatpacked{"lib/core/only.pm"} = <<'LIB_CORE_ONLY';
+$fatpacked{"lib/core/only.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIB_CORE_ONLY';
   package lib::core::only;
   
   use strict;
@@ -18968,12 +19466,17 @@ $fatpacked{"lib/core/only.pm"} = <<'LIB_CORE_ONLY';
   
   To get only the core directories plus the ones for the local::lib in scope:
   
-    $ perl -Mlib::core::only -Mlocal::lib=~/perl5 myscript.pl
+    $ perl -mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5 myscript.pl
   
   To attempt to do a self-contained build (but note this will not reliably
   propagate into subprocesses, see the CAVEATS below):
   
-    $ PERL5OPT='-Mlib::core::only -Mlocal::lib=~/perl5' cpan
+    $ PERL5OPT='-mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5' cpan
+  
+  Please note that it is necessary to use C<local::lib> twice for this to work.
+  First so that C<lib::core::only> doesn't prevent C<local::lib> from loading
+  (it's not currently in core) and then again after C<lib::core::only> so that
+  the local paths are not removed.
   
   =head1 DESCRIPTION
   
@@ -19044,39 +19547,31 @@ $fatpacked{"lib/core/only.pm"} = <<'LIB_CORE_ONLY';
   1;
 LIB_CORE_ONLY
 
-$fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
+$fatpacked{"local/lib.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LOCAL_LIB';
+  package local::lib;
+  use 5.006;
   use strict;
   use warnings;
+  use Config;
+  use File::Spec ();
   
-  package local::lib;
+  our $VERSION = '2.000008'; # 2.0.8
+  $VERSION = eval $VERSION;
   
-  use 5.008001; # probably works with earlier versions but I'm not supporting them
-                # (patches would, of course, be welcome)
+  sub import {
+    my ($class, @args) = @_;
+    push @args, @ARGV
+      if $0 eq '-';
   
-  use File::Spec ();
-  use File::Path ();
-  use Config;
-  
-  our $VERSION = '1.008011'; # 1.8.11
-  
-  our @KNOWN_FLAGS = qw(--self-contained --deactivate --deactivate-all);
-  
-  sub DEACTIVATE_ONE () { 1 }
-  sub DEACTIVATE_ALL () { 2 }
-  
-  sub INTERPOLATE_ENV () { 1 }
-  sub LITERAL_ENV     () { 0 }
-  
-  sub import {
-    my ($class, @args) = @_;
+    my @steps;
+    my %opts;
+    my $shelltype;
   
-    # Remember what PERL5LIB was when we started
-    my $perl5lib = $ENV{PERL5LIB} || '';
-  
-    my %arg_store;
-    for my $arg (@args) {
+    while (@args) {
+      my $arg = shift @args;
       # check for lethal dash first to stop processing before causing problems
-      if ($arg =~ /−/) {
+      # the fancy dash is U+2212 or \xE2\x88\x92
+      if ($arg =~ /\xE2\x88\x92/ or $arg =~ /−/) {
         die <<'DEATH';
   WHOA THERE! It looks like you've got some fancy dashes in your commandline!
   These are *not* the traditional -- dashes that software recognizes. You
@@ -19086,514 +19581,550 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   dashes with normal minus signs.
   DEATH
       }
-      elsif(grep { $arg eq $_ } @KNOWN_FLAGS) {
-        (my $flag = $arg) =~ s/--//;
-        $arg_store{$flag} = 1;
+      elsif ($arg eq '--self-contained') {
+        die <<'DEATH';
+  FATAL: The local::lib --self-contained flag has never worked reliably and the
+  original author, Mark Stosberg, was unable or unwilling to maintain it. As
+  such, this flag has been removed from the local::lib codebase in order to
+  prevent misunderstandings and potentially broken builds. The local::lib authors
+  recommend that you look at the lib::core::only module shipped with this
+  distribution in order to create a more robust environment that is equivalent to
+  what --self-contained provided (although quite possibly not what you originally
+  thought it provided due to the poor quality of the documentation, for which we
+  apologise).
+  DEATH
+      }
+      elsif( $arg =~ /^--deactivate(?:=(.*))?$/ ) {
+        my $path = defined $1 ? $1 : shift @args;
+        push @steps, ['deactivate', $path];
+      }
+      elsif ( $arg eq '--deactivate-all' ) {
+        push @steps, ['deactivate_all'];
       }
-      elsif($arg =~ /^--/) {
+      elsif ( $arg =~ /^--shelltype(?:=(.*))?$/ ) {
+        $shelltype = defined $1 ? $1 : shift @args;
+      }
+      elsif ( $arg eq '--no-create' ) {
+        $opts{no_create} = 1;
+      }
+      elsif ( $arg =~ /^--/ ) {
         die "Unknown import argument: $arg";
       }
       else {
-        # assume that what's left is a path
-        $arg_store{path} = $arg;
+        push @steps, ['activate', $arg];
       }
     }
-  
-    if($arg_store{'self-contained'}) {
-      die "FATAL: The local::lib --self-contained flag has never worked reliably and the original author, Mark Stosberg, was unable or unwilling to maintain it. As such, this flag has been removed from the local::lib codebase in order to prevent misunderstandings and potentially broken builds. The local::lib authors recommend that you look at the lib::core::only module shipped with this distribution in order to create a more robust environment that is equivalent to what --self-contained provided (although quite possibly not what you originally thought it provided due to the poor quality of the documentation, for which we apologise).\n";
-    }
-  
-    my $deactivating = 0;
-    if ($arg_store{deactivate}) {
-      $deactivating = DEACTIVATE_ONE;
-    }
-    if ($arg_store{'deactivate-all'}) {
-      $deactivating = DEACTIVATE_ALL;
+    if (!@steps) {
+      push @steps, ['activate', undef];
     }
   
-    $arg_store{path} = $class->resolve_path($arg_store{path});
-    $class->setup_local_lib_for($arg_store{path}, $deactivating);
+    my $self = $class->new(%opts);
   
-    for (@INC) { # Untaint @INC
-      next if ref; # Skip entry if it is an ARRAY, CODE, blessed, etc.
-      m/(.*)/ and $_ = $1;
+    for (@steps) {
+      my ($method, @args) = @$_;
+      $self = $self->$method(@args);
     }
-  }
-  
-  sub pipeline;
   
-  sub pipeline {
-    my @methods = @_;
-    my $last = pop(@methods);
-    if (@methods) {
-      \sub {
-        my ($obj, @args) = @_;
-        $obj->${pipeline @methods}(
-          $obj->$last(@args)
-        );
-      };
-    } else {
-      \sub {
-        shift->$last(@_);
-      };
+    if ($0 eq '-') {
+      print $self->environment_vars_string($shelltype);
+      exit 0;
+    }
+    else {
+      $self->setup_local_lib;
     }
   }
   
-  =begin testing
-  
-  #:: test pipeline
-  
-  package local::lib;
+  sub new {
+    my $class = shift;
+    bless {@_}, $class;
+  }
   
-  { package Foo; sub foo { -$_[1] } sub bar { $_[1]+2 } sub baz { $_[1]+3 } }
-  my $foo = bless({}, 'Foo');                                                 
-  Test::More::ok($foo->${pipeline qw(foo bar baz)}(10) == -15);
+  sub clone {
+    my $self = shift;
+    bless {%$self, @_}, ref $self;
+  }
+  
+  sub inc { $_[0]->{inc}     ||= \@INC }
+  sub libs { $_[0]->{libs}   ||= [ \'PERL5LIB' ] }
+  sub bins { $_[0]->{bins}   ||= [ \'PATH' ] }
+  sub roots { $_[0]->{roots} ||= [ \'PERL_LOCAL_LIB_ROOT' ] }
+  sub extra { $_[0]->{extra} ||= {} }
+  sub no_create { $_[0]->{no_create} }
+  
+  my $_archname = $Config{archname};
+  my $_version  = $Config{version};
+  my @_inc_version_list = reverse split / /, $Config{inc_version_list};
+  my $_path_sep = $Config{path_sep};
+  
+  sub _as_list {
+    my $list = shift;
+    grep length, map {
+      !(ref $_ && ref $_ eq 'SCALAR') ? $_ : (
+        defined $ENV{$$_} ? split(/\Q$_path_sep/, $ENV{$$_})
+                          : ()
+      )
+    } ref $list ? @$list : $list;
+  }
+  sub _remove_from {
+    my ($list, @remove) = @_;
+    return @$list
+      if !@remove;
+    my %remove = map { $_ => 1 } @remove;
+    grep !$remove{$_}, _as_list($list);
+  }
+  
+  my @_lib_subdirs = (
+    [$_version, $_archname],
+    [$_version],
+    [$_archname],
+    (@_inc_version_list ? \@_inc_version_list : ()),
+    [],
+  );
   
-  =end testing
+  sub install_base_bin_path {
+    my ($class, $path) = @_;
+    return File::Spec->catdir($path, 'bin');
+  }
+  sub install_base_perl_path {
+    my ($class, $path) = @_;
+    return File::Spec->catdir($path, 'lib', 'perl5');
+  }
+  sub install_base_arch_path {
+    my ($class, $path) = @_;
+    File::Spec->catdir($class->install_base_perl_path($path), $_archname);
+  }
   
-  =cut
+  sub lib_paths_for {
+    my ($class, $path) = @_;
+    my $base = $class->install_base_perl_path($path);
+    return map { File::Spec->catdir($base, @$_) } @_lib_subdirs;
+  }
   
-  sub _uniq {
-      my %seen;
-      grep { ! $seen{$_}++ } @_;
+  sub _mm_escape_path {
+    my $path = shift;
+    $path =~ s/\\/\\\\\\\\/g;
+    if ($path =~ s/ /\\ /g) {
+      $path = qq{"\\"$path\\""};
+    }
+    return $path;
   }
   
-  sub resolve_path {
-    my ($class, $path) = @_;
-    $class->${pipeline qw(
-      resolve_relative_path
-      resolve_home_path
-      resolve_empty_path
-    )}($path);
+  sub _mb_escape_path {
+    my $path = shift;
+    $path =~ s/\\/\\\\/g;
+    return qq{"$path"};
   }
   
-  sub resolve_empty_path {
+  sub installer_options_for {
     my ($class, $path) = @_;
-    if (defined $path) {
-      $path;
-    } else {
-      '~/perl5';
-    }
+    return (
+      PERL_MM_OPT =>
+        defined $path ? "INSTALL_BASE="._mm_escape_path($path) : undef,
+      PERL_MB_OPT =>
+        defined $path ? "--install_base "._mb_escape_path($path) : undef,
+    );
   }
   
-  =begin testing
+  sub active_paths {
+    my ($self) = @_;
+    $self = ref $self ? $self : $self->new;
   
-  #:: test classmethod setup
+    return grep {
+      # screen out entries that aren't actually reflected in @INC
+      my $active_ll = $self->install_base_perl_path($_);
+      grep { $_ eq $active_ll } @{$self->inc};
+    } _as_list($self->roots);
+  }
   
-  my $c = 'local::lib';
   
-  =end testing
+  sub deactivate {
+    my ($self, $path) = @_;
+    $self = $self->new unless ref $self;
+    $path = $self->resolve_path($path);
+    $path = $self->normalize_path($path);
   
-  =begin testing
+    my @active_lls = $self->active_paths;
   
-  #:: test classmethod
+    if (!grep { $_ eq $path } @active_lls) {
+      warn "Tried to deactivate inactive local::lib '$path'\n";
+      return $self;
+    }
   
-  is($c->resolve_empty_path, '~/perl5');
-  is($c->resolve_empty_path('foo'), 'foo');
+    my %args = (
+      bins  => [ _remove_from($self->bins,
+        $self->install_base_bin_path($path)) ],
+      libs  => [ _remove_from($self->libs,
+        $self->install_base_perl_path($path)) ],
+      inc   => [ _remove_from($self->inc,
+        $self->lib_paths_for($path)) ],
+      roots => [ _remove_from($self->roots, $path) ],
+    );
   
-  =end testing
+    $args{extra} = { $self->installer_options_for($args{roots}[0]) };
   
-  =cut
+    $self->clone(%args);
+  }
   
-  sub resolve_home_path {
-    my ($class, $path) = @_;
-    return $path unless ($path =~ /^~/);
-    my ($user) = ($path =~ /^~([^\/]+)/); # can assume ^~ so undef for 'us'
-    my $tried_file_homedir;
-    my $homedir = do {
-      if (eval { require File::HomeDir } && $File::HomeDir::VERSION >= 0.65) {
-        $tried_file_homedir = 1;
-        if (defined $user) {
-          File::HomeDir->users_home($user);
-        } else {
-          File::HomeDir->my_home;
-        }
-      } else {
-        if (defined $user) {
-          (getpwnam $user)[7];
-        } else {
-          if (defined $ENV{HOME}) {
-            $ENV{HOME};
-          } else {
-            (getpwuid $<)[7];
-          }
-        }
-      }
-    };
-    unless (defined $homedir) {
-      require Carp;
-      Carp::croak(
-        "Couldn't resolve homedir for "
-        .(defined $user ? $user : 'current user')
-        .($tried_file_homedir ? '' : ' - consider installing File::HomeDir')
+  sub deactivate_all {
+    my ($self) = @_;
+    $self = $self->new unless ref $self;
+  
+    my @active_lls = $self->active_paths;
+  
+    my %args;
+    if (@active_lls) {
+      %args = (
+        bins => [ _remove_from($self->bins,
+          map $self->install_base_bin_path($_), @active_lls) ],
+        libs => [ _remove_from($self->libs,
+          map $self->install_base_perl_path($_), @active_lls) ],
+        inc => [ _remove_from($self->inc,
+          map $self->lib_paths_for($_), @active_lls) ],
+        roots => [ _remove_from($self->roots, @active_lls) ],
       );
     }
-    $path =~ s/^~[^\/]*/$homedir/;
-    $path;
-  }
-  
-  sub resolve_relative_path {
-    my ($class, $path) = @_;
-    $path = File::Spec->rel2abs($path);
-  }
   
-  =begin testing
+    $args{extra} = { $self->installer_options_for(undef) };
   
-  #:: test classmethod
+    $self->clone(%args);
+  }
   
-  local *File::Spec::rel2abs = sub { shift; 'FOO'.shift; };
-  is($c->resolve_relative_path('bar'),'FOObar');
+  sub activate {
+    my ($self, $path) = @_;
+    $self = $self->new unless ref $self;
+    $path = $self->resolve_path($path);
+    $self->ensure_dir_structure_for($path)
+      unless $self->no_create;
   
-  =end testing
+    $path = $self->normalize_path($path);
   
-  =cut
+    my @active_lls = $self->active_paths;
   
-  sub setup_local_lib_for {
-    my ($class, $path, $deactivating) = @_;
-  
-    my $interpolate = LITERAL_ENV;
-    my @active_lls = $class->active_paths;
-  
-    $class->ensure_dir_structure_for($path);
-  
-    # On Win32 directories often contain spaces. But some parts of the CPAN
-    # toolchain don't like that. To avoid this, GetShortPathName() gives us
-    # an alternate representation that has none.
-    # This only works if the directory already exists.
-    $path = Win32::GetShortPathName($path) if $^O eq 'MSWin32';
-  
-    if (! $deactivating) {
-      if (@active_lls && $active_lls[-1] eq $path) {
-        exit 0 if $0 eq '-';
-        return; # Asked to add what's already at the top of the stack
-      } elsif (grep { $_ eq $path} @active_lls) {
-        # Asked to add a dir that's lower in the stack -- so we remove it from
-        # where it is, and then add it back at the top.
-        $class->setup_env_hash_for($path, DEACTIVATE_ONE);
-        # Which means we can no longer output "PERL5LIB=...:$PERL5LIB" stuff
-        # anymore because we're taking something *out*.
-        $interpolate = INTERPOLATE_ENV;
-      }
+    if (grep { $_ eq $path } @active_lls[1 .. $#active_lls]) {
+      $self = $self->deactivate($path);
     }
   
-    if ($0 eq '-') {
-      $class->print_environment_vars_for($path, $deactivating, $interpolate);
-      exit 0;
-    } else {
-      $class->setup_env_hash_for($path, $deactivating);
-      my $arch_dir = $Config{archname};
-      @INC = _uniq(
-    (
-        # Inject $path/$archname for each path in PERL5LIB
-        map { ( File::Spec->catdir($_, $arch_dir), $_ ) }
-        split($Config{path_sep}, $ENV{PERL5LIB})
-    ),
-    @INC
+    my %args;
+    if (!@active_lls || $active_lls[0] ne $path) {
+      %args = (
+        bins  => [ $self->install_base_bin_path($path), @{$self->bins} ],
+        libs  => [ $self->install_base_perl_path($path), @{$self->libs} ],
+        inc   => [ $self->lib_paths_for($path), @{$self->inc} ],
+        roots => [ $path, @{$self->roots} ],
       );
     }
-  }
   
-  sub install_base_bin_path {
-    my ($class, $path) = @_;
-    File::Spec->catdir($path, 'bin');
+    $args{extra} = { $self->installer_options_for($path) };
+  
+    $self->clone(%args);
   }
   
-  sub install_base_perl_path {
-    my ($class, $path) = @_;
-    File::Spec->catdir($path, 'lib', 'perl5');
+  sub normalize_path {
+    my ($self, $path) = @_;
+    $path = ( Win32::GetShortPathName($path) || $path )
+      if $^O eq 'MSWin32';
+    return $path;
   }
   
-  sub install_base_arch_path {
-    my ($class, $path) = @_;
-    File::Spec->catdir($class->install_base_perl_path($path), $Config{archname});
+  sub build_environment_vars_for {
+    my $self = $_[0]->new->activate($_[1]);
+    $self->build_environment_vars;
+  }
+  sub build_environment_vars {
+    my $self = shift;
+    (
+      PATH                => join($_path_sep, _as_list($self->bins)),
+      PERL5LIB            => join($_path_sep, _as_list($self->libs)),
+      PERL_LOCAL_LIB_ROOT => join($_path_sep, _as_list($self->roots)),
+      %{$self->extra},
+    );
   }
   
-  sub ensure_dir_structure_for {
-    my ($class, $path) = @_;
-    unless (-d $path) {
-      warn "Attempting to create directory ${path}\n";
-    }
-    File::Path::mkpath($path);
-    return
+  sub setup_local_lib_for {
+    my $self = $_[0]->new->activate($_[1]);
+    $self->setup_local_lib;
   }
   
-  sub guess_shelltype {
-    my $shellbin = 'sh';
-    if(defined $ENV{'SHELL'}) {
-        my @shell_bin_path_parts = File::Spec->splitpath($ENV{'SHELL'});
-        $shellbin = $shell_bin_path_parts[-1];
-    }
-    my $shelltype = do {
-        local $_ = $shellbin;
-        if(/csh/) {
-            'csh'
-        } else {
-            'bourne'
-        }
-    };
+  sub setup_local_lib {
+    my $self = shift;
+    $self->setup_env_hash;
+    @INC = @{$self->inc};
+  }
   
-    # Both Win32 and Cygwin have $ENV{COMSPEC} set.
-    if (defined $ENV{'COMSPEC'} && $^O ne 'cygwin') {
-        my @shell_bin_path_parts = File::Spec->splitpath($ENV{'COMSPEC'});
-        $shellbin = $shell_bin_path_parts[-1];
-           $shelltype = do {
-                   local $_ = $shellbin;
-                   if(/command\.com/) {
-                           'win32'
-                   } elsif(/cmd\.exe/) {
-                           'win32'
-                   } elsif(/4nt\.exe/) {
-                           'win32'
-                   } else {
-                           $shelltype
-                   }
-           };
+  sub setup_env_hash_for {
+    my $self = $_[0]->new->activate($_[1]);
+    $self->setup_env_hash;
+  }
+  sub setup_env_hash {
+    my $self = shift;
+    my %env = $self->build_environment_vars;
+    for my $key (keys %env) {
+      if (defined $env{$key}) {
+        $ENV{$key} = $env{$key};
+      }
+      else {
+        delete $ENV{$key};
+      }
     }
-    return $shelltype;
   }
   
   sub print_environment_vars_for {
-    my ($class, $path, $deactivating, $interpolate) = @_;
-    print $class->environment_vars_string_for($path, $deactivating, $interpolate);
+    print $_[0]->environment_vars_string_for(@_[1..$#_]);
   }
   
   sub environment_vars_string_for {
-    my ($class, $path, $deactivating, $interpolate) = @_;
-    my @envs = $class->build_environment_vars_for($path, $deactivating, $interpolate);
-    my $out = '';
+    my $self = $_[0]->new->activate($_[1]);
+    $self->environment_vars_string;
+  }
+  sub environment_vars_string {
+    my ($self, $shelltype) = @_;
   
-    # rather basic csh detection, goes on the assumption that something won't
-    # call itself csh unless it really is. also, default to bourne in the
-    # pathological situation where a user doesn't have $ENV{SHELL} defined.
-    # note also that shells with funny names, like zoid, are assumed to be
-    # bourne.
+    $shelltype ||= $self->guess_shelltype;
   
-    my $shelltype = $class->guess_shelltype;
+    my $build_method = "build_${shelltype}_env_declaration";
   
+    my $extra = $self->extra;
+    my @envs = (
+      PATH                => $self->bins,
+      PERL5LIB            => $self->libs,
+      PERL_LOCAL_LIB_ROOT => $self->roots,
+      map { $_ => $extra->{$_} } sort keys %$extra,
+    );
+    my $out = '';
     while (@envs) {
       my ($name, $value) = (shift(@envs), shift(@envs));
-      $value =~ s/(\\")/\\$1/g if defined $value;
-      $out .= $class->${\"build_${shelltype}_env_declaration"}($name, $value);
+      if (
+          ref $value
+          && @$value == 1
+          && ref $value->[0]
+          && ref $value->[0] eq 'SCALAR'
+          && ${$value->[0]} eq $name) {
+        next;
+      }
+      if (
+          !ref $value
+          and defined $value
+            ? (defined $ENV{$name} && $value eq $ENV{$name})
+            : !defined $ENV{$name}
+      ) {
+        next;
+      }
+      $out .= $self->$build_method($name, $value);
+    }
+    my $wrap_method = "wrap_${shelltype}_output";
+    if ($self->can($wrap_method)) {
+      return $self->$wrap_method($out);
     }
     return $out;
   }
   
-  # simple routines that take two arguments: an %ENV key and a value. return
-  # strings that are suitable for passing directly to the relevant shell to set
-  # said key to said value.
   sub build_bourne_env_declaration {
-    my $class = shift;
-    my($name, $value) = @_;
-    return defined($value) ? qq{export ${name}="${value}";\n} : qq{unset ${name};\n};
-  }
+    my ($class, $name, $args) = @_;
+    my $value = $class->_interpolate($args, '$%s', '"', '\\%s');
   
-  sub build_csh_env_declaration {
-    my $class = shift;
-    my($name, $value) = @_;
-    return defined($value) ? qq{setenv ${name} "${value}"\n} : qq{unsetenv ${name}\n};
-  }
+    if (!defined $value) {
+      return qq{unset $name;\n};
+    }
   
-  sub build_win32_env_declaration {
-    my $class = shift;
-    my($name, $value) = @_;
-    return defined($value) ? qq{set ${name}=${value}\n} : qq{set ${name}=\n};
-  }
+    $value =~ s/(^|\G|$_path_sep)\$$name$_path_sep/$1\$$name\${$name+$_path_sep}/g;
+    $value =~ s/$_path_sep\$$name$/\${$name+$_path_sep}\$$name/;
   
-  sub setup_env_hash_for {
-    my ($class, $path, $deactivating) = @_;
-    my %envs = $class->build_environment_vars_for($path, $deactivating, INTERPOLATE_ENV);
-    @ENV{keys %envs} = values %envs;
+    qq{${name}="$value"; export ${name};\n}
   }
   
-  sub build_environment_vars_for {
-    my ($class, $path, $deactivating, $interpolate) = @_;
-  
-    if ($deactivating == DEACTIVATE_ONE) {
-      return $class->build_deactivate_environment_vars_for($path, $interpolate);
-    } elsif ($deactivating == DEACTIVATE_ALL) {
-      return $class->build_deact_all_environment_vars_for($path, $interpolate);
-    } else {
-      return $class->build_activate_environment_vars_for($path, $interpolate);
+  sub build_csh_env_declaration {
+    my ($class, $name, $args) = @_;
+    my ($value, @vars) = $class->_interpolate($args, '$%s', '"', '"\\%s"');
+    if (!defined $value) {
+      return qq{unsetenv $name;\n};
     }
-  }
   
-  # Build an environment value for a variable like PATH from a list of paths.
-  # References to existing variables are given as references to the variable name.
-  # Duplicates are removed.
-  #
-  # options:
-  # - interpolate: INTERPOLATE_ENV/LITERAL_ENV
-  # - exists: paths are included only if they exist (default: interpolate == INTERPOLATE_ENV)
-  # - filter: function to apply to each path do decide if it must be included
-  # - empty: the value to return in the case of empty value
-  my %ENV_LIST_VALUE_DEFAULTS = (
-      interpolate => INTERPOLATE_ENV,
-      exists => undef,
-      filter => sub { 1 },
-      empty => undef,
-  );
-  sub _env_list_value {
-    my $options = shift;
-    die(sprintf "unknown option '$_' at %s line %u\n", (caller)[1..2])
-      for grep { !exists $ENV_LIST_VALUE_DEFAULTS{$_} } keys %$options;
-    my %options = (%ENV_LIST_VALUE_DEFAULTS, %{ $options });
-    $options{exists} = $options{interpolate} == INTERPOLATE_ENV
-      unless defined $options{exists};
-  
-    my %seen;
-  
-    my $value = join($Config{path_sep}, map {
-        ref $_ ? ($^O eq 'MSWin32' ? "%${$_}%" : "\$${$_}") : $_
-      } grep {
-        ref $_ || (defined $_
-                   && length($_) > 0
-                   && !$seen{$_}++
-                   && $options{filter}->($_)
-                   && (!$options{exists} || -e $_))
-      } map {
-        if (ref $_ eq 'SCALAR' && $options{interpolate} == INTERPOLATE_ENV) {
-          defined $ENV{${$_}} ? (split /\Q$Config{path_sep}/, $ENV{${$_}}) : ()
-        } else {
-          $_
-        }
-      } @_);
-    return length($value) ? $value : $options{empty};
-  }
+    my $out = '';
+    for my $var (@vars) {
+      $out .= qq{if ! \$?$name setenv $name '';\n};
+    }
   
-  sub build_activate_environment_vars_for {
-    my ($class, $path, $interpolate) = @_;
-    return (
-      PERL_LOCAL_LIB_ROOT =>
-              _env_list_value(
-                { interpolate => $interpolate, exists => 0, empty => '' },
-                \'PERL_LOCAL_LIB_ROOT',
-                $path,
-              ),
-      PERL_MB_OPT => "--install_base ${path}",
-      PERL_MM_OPT => "INSTALL_BASE=${path}",
-      PERL5LIB =>
-              _env_list_value(
-                { interpolate => $interpolate, exists => 0, empty => '' },
-                $class->install_base_perl_path($path),
-                \'PERL5LIB',
-              ),
-      PATH => _env_list_value(
-                { interpolate => $interpolate, exists => 0, empty => '' },
-          $class->install_base_bin_path($path),
-                \'PATH',
-              ),
-    )
+    my $value_without = $value;
+    if ($value_without =~ s/(?:^|$_path_sep)\$$name(?:$_path_sep|$)//g) {
+      $out .= qq{if "\$$name" != '' setenv $name "$value";\n};
+      $out .= qq{if "\$$name" == '' };
+    }
+    $out .= qq{setenv $name "$value_without";\n};
+    return $out;
   }
   
-  sub active_paths {
-    my ($class) = @_;
+  sub build_cmd_env_declaration {
+    my ($class, $name, $args) = @_;
+    my $value = $class->_interpolate($args, '%%%s%%', qr([()!^"<>&|]), '^%s');
+    if (!$value) {
+      return qq{\@set $name=\n};
+    }
   
-    return () unless defined $ENV{PERL_LOCAL_LIB_ROOT};
-    return grep { $_ ne '' } split /\Q$Config{path_sep}/, $ENV{PERL_LOCAL_LIB_ROOT};
+    my $out = '';
+    my $value_without = $value;
+    if ($value_without =~ s/(?:^|$_path_sep)%$name%(?:$_path_sep|$)//g) {
+      $out .= qq{\@if not "%$name%"=="" set $name=$value\n};
+      $out .= qq{\@if "%$name%"=="" };
+    }
+    $out .= qq{\@set $name=$value_without\n};
+    return $out;
   }
   
-  sub build_deactivate_environment_vars_for {
-    my ($class, $path, $interpolate) = @_;
+  sub build_powershell_env_declaration {
+    my ($class, $name, $args) = @_;
+    my $value = $class->_interpolate($args, '$env:%s', '"', '`%s');
   
-    my @active_lls = $class->active_paths;
-  
-    if (!grep { $_ eq $path } @active_lls) {
-      warn "Tried to deactivate inactive local::lib '$path'\n";
-      return ();
+    if (!$value) {
+      return qq{Remove-Item -ErrorAction 0 Env:\\$name;\n};
     }
   
-    my $perl_path = $class->install_base_perl_path($path);
-    my $arch_path = $class->install_base_arch_path($path);
-    my $bin_path = $class->install_base_bin_path($path);
+    my $maybe_path_sep = qq{\$(if("\$env:$name"-eq""){""}else{"$_path_sep"})};
+    $value =~ s/(^|\G|$_path_sep)\$env:$name$_path_sep/$1\$env:$name"+$maybe_path_sep+"/g;
+    $value =~ s/$_path_sep\$env:$name$/"+$maybe_path_sep+\$env:$name+"/;
   
+    qq{\$env:$name = \$("$value");\n};
+  }
+  sub wrap_powershell_output {
+    my ($class, $out) = @_;
+    return $out || " \n";
+  }
   
-    my %env = (
-      PERL_LOCAL_LIB_ROOT => _env_list_value(
-        {
-          exists => 0,
-        },
-        grep { $_ ne $path } @active_lls
-      ),
-      PERL5LIB => _env_list_value(
-        {
-          exists => 0,
-          filter => sub {
-            $_ ne $perl_path && $_ ne $arch_path
-          },
-        },
-        \'PERL5LIB',
-      ),
-      PATH => _env_list_value(
-        {
-          exists => 0,
-          filter => sub { $_ ne $bin_path },
-        },
-        \'PATH',
-      ),
-    );
-  
-    # If removing ourselves from the "top of the stack", set install paths to
-    # correspond with the new top of stack.
-    if ($active_lls[-1] eq $path) {
-      my $new_top = $active_lls[-2];
-      $env{PERL_MB_OPT} = defined($new_top) ? "--install_base ${new_top}" : undef;
-      $env{PERL_MM_OPT} = defined($new_top) ? "INSTALL_BASE=${new_top}" : undef;
+  sub build_fish_env_declaration {
+    my ($class, $name, $args) = @_;
+    my $value = $class->_interpolate($args, '$%s', '"', '\\%s');
+    if (!defined $value) {
+      return qq{set -e $name;\n};
     }
+    $value =~ s/$_path_sep/ /g;
+    qq{set -x $name $value;\n};
+  }
   
-    return %env;
+  sub _interpolate {
+    my ($class, $args, $var_pat, $escape, $escape_pat) = @_;
+    return
+      unless defined $args;
+    my @args = ref $args ? @$args : $args;
+    return
+      unless @args;
+    my @vars = map { $$_ } grep { ref $_ eq 'SCALAR' } @args;
+    my $string = join $_path_sep, map {
+      ref $_ eq 'SCALAR' ? sprintf($var_pat, $$_) : do {
+        s/($escape)/sprintf($escape_pat, $1)/ge; $_;
+      };
+    } @args;
+    return wantarray ? ($string, \@vars) : $string;
   }
   
-  sub build_deact_all_environment_vars_for {
-    my ($class, $path, $interpolate) = @_;
+  sub pipeline;
   
-    my @active_lls = $class->active_paths;
+  sub pipeline {
+    my @methods = @_;
+    my $last = pop(@methods);
+    if (@methods) {
+      \sub {
+        my ($obj, @args) = @_;
+        $obj->${pipeline @methods}(
+          $obj->$last(@args)
+        );
+      };
+    } else {
+      \sub {
+        shift->$last(@_);
+      };
+    }
+  }
   
-    my %perl_paths = map { (
-        $class->install_base_perl_path($_) => 1,
-        $class->install_base_arch_path($_) => 1
-      ) } @active_lls;
-    my %bin_paths = map { (
-        $class->install_base_bin_path($_) => 1,
-      ) } @active_lls;
+  sub resolve_path {
+    my ($class, $path) = @_;
   
-    my %env = (
-      PERL_LOCAL_LIB_ROOT => undef,
-      PERL_MM_OPT => undef,
-      PERL_MB_OPT => undef,
-      PERL5LIB => _env_list_value(
-        {
-          exists => 0,
-          filter => sub {
-            ! scalar grep { exists $perl_paths{$_} } $_[0]
-          },
-        },
-        \'PERL5LIB'
-      ),
-      PATH => _env_list_value(
-        {
-          exists => 0,
-          filter => sub {
-            ! scalar grep { exists $bin_paths{$_} } $_[0]
-          },
-        },
-        \'PATH'
-      ),
-    );
+    $path = $class->${pipeline qw(
+      resolve_relative_path
+      resolve_home_path
+      resolve_empty_path
+    )}($path);
   
-    return %env;
+    $path;
   }
   
-  =begin testing
+  sub resolve_empty_path {
+    my ($class, $path) = @_;
+    if (defined $path) {
+      $path;
+    } else {
+      '~/perl5';
+    }
+  }
   
-  #:: test classmethod
+  sub resolve_home_path {
+    my ($class, $path) = @_;
+    $path =~ /^~([^\/]*)/ or return $path;
+    my $user = $1;
+    my $homedir = do {
+      if (! length($user) && defined $ENV{HOME}) {
+        $ENV{HOME};
+      }
+      else {
+        require File::Glob;
+        File::Glob::bsd_glob("~$user", File::Glob::GLOB_TILDE());
+      }
+    };
+    unless (defined $homedir) {
+      require Carp;
+      Carp::croak(
+        "Couldn't resolve homedir for "
+        .(defined $user ? $user : 'current user')
+      );
+    }
+    $path =~ s/^~[^\/]*/$homedir/;
+    $path;
+  }
   
-  File::Path::rmtree('t/var/splat');
+  sub resolve_relative_path {
+    my ($class, $path) = @_;
+    $path = File::Spec->rel2abs($path);
+  }
   
-  $c->ensure_dir_structure_for('t/var/splat');
+  sub ensure_dir_structure_for {
+    my ($class, $path) = @_;
+    unless (-d $path) {
+      warn "Attempting to create directory ${path}\n";
+    }
+    require File::Basename;
+    my @dirs;
+    while(!-d $path) {
+      push @dirs, $path;
+      $path = File::Basename::dirname($path);
+    }
+    mkdir $_ for reverse @dirs;
+    return;
+  }
   
-  ok(-d 't/var/splat');
+  sub guess_shelltype {
+    my $shellbin
+      = defined $ENV{SHELL}
+        ? ($ENV{SHELL} =~ /([\w.]+)$/)[-1]
+      : ( $^O eq 'MSWin32' && exists $ENV{'!EXITCODE'} )
+        ? 'bash'
+      : ( $^O eq 'MSWin32' && $ENV{PROMPT} && $ENV{COMSPEC} )
+        ? ($ENV{COMSPEC} =~ /([\w.]+)$/)[-1]
+      : ( $^O eq 'MSWin32' && !$ENV{PROMPT} )
+        ? 'powershell.exe'
+      : 'sh';
+  
+    for ($shellbin) {
+      return
+          /csh$/                   ? 'csh'
+        : /fish/                   ? 'fish'
+        : /command(?:\.com)?$/i    ? 'cmd'
+        : /cmd(?:\.exe)?$/i        ? 'cmd'
+        : /4nt(?:\.exe)?$/i        ? 'cmd'
+        : /powershell(?:\.exe)?$/i ? 'powershell'
+                                   : 'bourne';
+    }
+  }
   
-  =end testing
+  1;
+  __END__
   
   =encoding utf8
   
@@ -19620,19 +20151,24 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
     # Just print out useful shell commands
     $ perl -Mlocal::lib
-    export PERL_MB_OPT='--install_base /home/username/perl5'
-    export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5'
-    export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5'
-    export PATH="/home/username/perl5/bin:$PATH"
+    PERL_MB_OPT='--install_base /home/username/perl5'; export PERL_MB_OPT;
+    PERL_MM_OPT='INSTALL_BASE=/home/username/perl5'; export PERL_MM_OPT;
+    PERL5LIB="/home/username/perl5/lib/perl5"; export PERL5LIB;
+    PATH="/home/username/perl5/bin:$PATH"; export PATH;
+    PERL_LOCAL_LIB_ROOT="/home/usename/perl5:$PERL_LOCAL_LIB_ROOT"; export PERL_LOCAL_LIB_ROOT;
+  
+  From a .bashrc file -
+  
+    [ $SHLVL -eq 1 ] && eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"
   
   =head2 The bootstrapping technique
   
   A typical way to install local::lib is using what is known as the
   "bootstrapping" technique.  You would do this if your system administrator
   hasn't already installed local::lib.  In this case, you'll need to install
-  local::lib in your home directory. 
+  local::lib in your home directory.
   
-  If you do have administrative privileges, you will still want to set up your 
+  Even if you do have administrative privileges, you will still want to set up your
   environment variables, as discussed in step 4. Without this, you would still
   install the modules into the system CPAN installation and also your Perl scripts
   will not use the lib/ path you bootstrapped with local::lib.
@@ -19641,12 +20177,18 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
   Windows users must also see L</Differences when using this module under Win32>.
   
-  1. Download and unpack the local::lib tarball from CPAN (search for "Download"
+  =over 4
+  
+  =item 1.
+  
+  Download and unpack the local::lib tarball from CPAN (search for "Download"
   on the CPAN page about local::lib).  Do this as an ordinary user, not as root
   or administrator.  Unpack the file in your home directory or in any other
   convenient location.
   
-  2. Run this:
+  =item 2.
+  
+  Run this:
   
     perl Makefile.PL --bootstrap
   
@@ -19658,42 +20200,49 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
     perl Makefile.PL --bootstrap=~/foo
   
-  3. Run this: (local::lib assumes you have make installed on your system)
+  =item 3.
+  
+  Run this: (local::lib assumes you have make installed on your system)
   
     make test && make install
   
-  4. Now we need to setup the appropriate environment variables, so that Perl 
+  =item 4.
+  
+  Now we need to setup the appropriate environment variables, so that Perl
   starts using our newly generated lib/ directory. If you are using bash or
   any other Bourne shells, you can add this to your shell startup script this
   way:
   
-    echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >>~/.bashrc
+    echo '[ $SHLVL -eq 1 ] && eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"' >>~/.bashrc
   
   If you are using C shell, you can do this as follows:
   
     /bin/csh
     echo $SHELL
     /bin/csh
-    perl -I$HOME/perl5/lib/perl5 -Mlocal::lib >> ~/.cshrc
+    echo 'eval `perl -I$HOME/perl5/lib/perl5 -Mlocal::lib`' >> ~/.cshrc
   
-  If you passed to bootstrap a directory other than default, you also need to give that as 
-  import parameter to the call of the local::lib module like this way:
+  If you passed to bootstrap a directory other than default, you also need to
+  give that as import parameter to the call of the local::lib module like this
+  way:
   
-    echo 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' >>~/.bashrc
+    echo '[ $SHLVL -eq 1 ] && eval "$(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)"' >>~/.bashrc
   
   After writing your shell configuration file, be sure to re-read it to get the
-  changed settings into your current shell's environment. Bourne shells use 
+  changed settings into your current shell's environment. Bourne shells use
   C<. ~/.bashrc> for this, whereas C shells use C<source ~/.cshrc>.
   
+  =back
+  
   If you're on a slower machine, or are operating under draconian disk space
   limitations, you can disable the automatic generation of manpages from POD when
   installing modules by using the C<--no-manpages> argument when bootstrapping:
   
     perl Makefile.PL --bootstrap --no-manpages
   
-  To avoid doing several bootstrap for several Perl module environments on the 
-  same account, for example if you use it for several different deployed 
-  applications independently, you can use one bootstrapped local::lib 
+  To avoid doing several bootstrap for several Perl module environments on the
+  same account, for example if you use it for several different deployed
+  applications independently, you can use one bootstrapped local::lib
   installation to install modules in different directories directly this way:
   
     cd ~/mydir1
@@ -19704,6 +20253,12 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
     cd ../mydir2
     ... REPEAT ...
   
+  When used in a C<.bashrc> file, it is recommended that you protect against
+  re-activating a directory in a sub-shell.  This can be done by checking the
+  C<$SHLVL> variable as shown in synopsis.  Without this, sub-shells created by
+  the user or other programs will override changes made to the parent shell's
+  environment.
+  
   If you are working with several C<local::lib> environments, you may want to
   remove some of them from the current environment without disturbing the others.
   You can deactivate one environment like this (using bourne sh):
@@ -19744,14 +20299,14 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
     C:\>perl -Mlocal::lib
     set PERL_MB_OPT=--install_base C:\DOCUME~1\ADMINI~1\perl5
     set PERL_MM_OPT=INSTALL_BASE=C:\DOCUME~1\ADMINI~1\perl5
-    set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5;C:\DOCUME~1\ADMINI~1\perl5\lib\perl5\MSWin32-x86-multi-thread
+    set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5
     set PATH=C:\DOCUME~1\ADMINI~1\perl5\bin;%PATH%
-    
+  
     ### To set the environment for this shell alone
     C:\>perl -Mlocal::lib > %TEMP%\tmp.bat && %TEMP%\tmp.bat && del %TEMP%\tmp.bat
     ### instead of $(perl -Mlocal::lib=./)
   
-  If you want the environment entries to persist, you'll need to add then to the
+  If you want the environment entries to persist, you'll need to add them to the
   Control Panel's System applet yourself or use L<App::local::lib::Win32Helper>.
   
   The "~" is translated to the user's profile directory (the directory named for
@@ -19760,6 +20315,13 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   directory is translated to a short name (which means the directory must exist)
   and the subdirectories are created.
   
+  =head3 PowerShell
+  
+  local::lib also supports PowerShell, and can be used with the
+  C<Invoke-Expression> cmdlet.
+  
+    Invoke-Expression "$(perl -Mlocal::lib)"
+  
   =head1 RATIONALE
   
   The version of a Perl package on your machine is not always the version you
@@ -19780,7 +20342,7 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   If you are using a package management system (such as Debian), you don't need to
   worry about Debian and CPAN stepping on each other's toes.  Your local version
   of the packages will be written to an entirely separate directory from those
-  installed by Debian.  
+  installed by Debian.
   
   =head1 DESCRIPTION
   
@@ -19810,10 +20372,12 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
   =item PATH
   
-  PATH is appended to, rather than clobbered.
+  =item PERL_LOCAL_LIB_ROOT
   
   =back
   
+  When possible, these will be appended to instead of overwritten entirely.
+  
   These values are then available for reference by any code after import.
   
   =head1 CREATING A SELF-CONTAINED SET OF MODULES
@@ -19822,7 +20386,7 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   there are a number of caveats, and the best approach is always to perform a
   build against a clean perl (i.e. site and vendor as close to empty as possible).
   
-  =head1 OPTIONS
+  =head1 IMPORT OPTIONS
   
   Options are values that can be passed to the C<local::lib> import besides the
   directory to use. They are specified as C<use local::lib '--option'[, path];>
@@ -19838,7 +20402,18 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   Remove all directories that were added to search paths by C<local::lib> from the
   search paths.
   
-  =head1 METHODS
+  =head2 --shelltype
+  
+  Specify the shell type to use for output.  By default, the shell will be
+  detected based on the environment.  Should be one of: C<bourne>, C<csh>,
+  C<cmd>, or C<powershell>.
+  
+  =head2 --no-create
+  
+  Prevents C<local::lib> from creating directories when activating dirs.  This is
+  likely to cause issues on Win32 systems.
+  
+  =head1 CLASS METHODS
   
   =head2 ensure_dir_structure_for
   
@@ -19870,9 +20445,9 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
   =over 4
   
-  =item Arguments: $path, $interpolate
+  =item Arguments: $path
   
-  =item Return value: \%environment_vars
+  =item Return value: %environment_vars
   
   =back
   
@@ -19903,7 +20478,8 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   =back
   
   Returns a list of active C<local::lib> paths, according to the
-  C<PERL_LOCAL_LIB_ROOT> environment variable.
+  C<PERL_LOCAL_LIB_ROOT> environment variable and verified against
+  what is really in C<@INC>.
   
   =head2 install_base_perl_path
   
@@ -19919,20 +20495,19 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   library installation. Appends the directories C<lib> and C<perl5> to the given
   path.
   
-  =head2 install_base_arch_path
+  =head2 lib_paths_for
   
   =over 4
   
   =item Arguments: $path
   
-  =item Return value: $install_base_arch_path
+  =item Return value: @lib_paths
   
   =back
   
-  Returns a path describing where to install the architecture-specific Perl
-  modules for this local library installation. Based on the
-  L</install_base_perl_path> method's return value, and appends the value of
-  C<$Config{archname}>.
+  Returns the list of paths perl will search for libraries, given a base path.
+  This includes the base path itself, the architecture specific subdirectory, and
+  perl version specific subdirectories.  These paths may not all exist.
   
   =head2 install_base_bin_path
   
@@ -19945,8 +20520,20 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   =back
   
   Returns a path describing where to install the executable programs for this
-  local library installation. Based on the L</install_base_perl_path> method's
-  return value, and appends the directory C<bin>.
+  local library installation. Appends the directory C<bin> to the given path.
+  
+  =head2 installer_options_for
+  
+  =over 4
+  
+  =item Arguments: $path
+  
+  =item Return value: %installer_env_vars
+  
+  =back
+  
+  Returns a hash of environment variables that should be set to cause
+  installation into the given path.
   
   =head2 resolve_empty_path
   
@@ -20005,6 +20592,141 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   L</resolve_relative_path>. The result of this final call is returned from
   L</resolve_path>.
   
+  =head1 OBJECT INTERFACE
+  
+  =head2 new
+  
+  =over 4
+  
+  =item Arguments: %attributes
+  
+  =item Return value: $local_lib
+  
+  =back
+  
+  Constructs a new C<local::lib> object, representing the current state of
+  C<@INC> and the relevant environment variables.
+  
+  =head1 ATTRIBUTES
+  
+  =head2 roots
+  
+  An arrayref representing active C<local::lib> directories.
+  
+  =head2 inc
+  
+  An arrayref representing C<@INC>.
+  
+  =head2 libs
+  
+  An arrayref representing the PERL5LIB environment variable.
+  
+  =head2 bins
+  
+  An arrayref representing the PATH environment variable.
+  
+  =head2 extra
+  
+  A hashref of extra environment variables (e.g. C<PERL_MM_OPT> and
+  C<PERL_MB_OPT>)
+  
+  =head2 no_create
+  
+  If set, C<local::lib> will not try to create directories when activating them.
+  
+  =head1 OBJECT METHODS
+  
+  =head2 clone
+  
+  =over 4
+  
+  =item Arguments: %attributes
+  
+  =item Return value: $local_lib
+  
+  =back
+  
+  Constructs a new C<local::lib> object based on the existing one, overriding the
+  specified attributes.
+  
+  =head2 activate
+  
+  =over 4
+  
+  =item Arguments: $path
+  
+  =item Return value: $new_local_lib
+  
+  =back
+  
+  Constructs a new instance with the specified path active.
+  
+  =head2 deactivate
+  
+  =over 4
+  
+  =item Arguments: $path
+  
+  =item Return value: $new_local_lib
+  
+  =back
+  
+  Constructs a new instance with the specified path deactivated.
+  
+  =head2 deactivate_all
+  
+  =over 4
+  
+  =item Arguments: None
+  
+  =item Return value: $new_local_lib
+  
+  =back
+  
+  Constructs a new instance with all C<local::lib> directories deactivated.
+  
+  =head2 environment_vars_string
+  
+  =over 4
+  
+  =item Arguments: [ $shelltype ]
+  
+  =item Return value: $shell_env_string
+  
+  =back
+  
+  Returns a string to set up the C<local::lib>, meant to be run by a shell.
+  
+  =head2 build_environment_vars
+  
+  =over 4
+  
+  =item Arguments: None
+  
+  =item Return value: %environment_vars
+  
+  =back
+  
+  Returns a hash with the variables listed above, properly set to use the
+  given path as the base directory.
+  
+  =head2 setup_env_hash
+  
+  =over 4
+  
+  =item Arguments: None
+  
+  =item Return value: None
+  
+  =back
+  
+  Constructs the C<%ENV> keys for the given path, by calling
+  L</build_environment_vars>.
+  
+  =head2 setup_local_lib
+  
+  Constructs the C<%ENV> hash using L</setup_env_hash>, and set up C<@INC>.
+  
   =head1 A WARNING ABOUT UNINST=1
   
   Be careful about using local::lib in combination with "make install UNINST=1".
@@ -20017,28 +20739,52 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   
   =head1 LIMITATIONS
   
-  The perl toolchain is unable to handle directory names with spaces in it,
-  so you cant put your local::lib bootstrap into a directory with spaces. What
-  you can do is moving your local::lib to a directory with spaces B<after> you
-  installed all modules inside your local::lib bootstrap. But be aware that you
-  cant update or install CPAN modules after the move.
+  =over 4
+  
+  =item * Directory names with spaces in them are not well supported by the perl
+  toolchain and the programs it uses.  Pure-perl distributions should support
+  spaces, but problems are more likely with dists that require compilation. A
+  workaround you can do is moving your local::lib to a directory with spaces
+  B<after> you installed all modules inside your local::lib bootstrap. But be
+  aware that you can't update or install CPAN modules after the move.
   
-  Rather basic shell detection. Right now anything with csh in its name is
+  =item * Rather basic shell detection. Right now anything with csh in its name is
   assumed to be a C shell or something compatible, and everything else is assumed
   to be Bourne, except on Win32 systems. If the C<SHELL> environment variable is
   not set, a Bourne-compatible shell is assumed.
   
-  Bootstrap is a hack and will use CPAN.pm for ExtUtils::MakeMaker even if you
-  have CPANPLUS installed.
+  =item * Kills any existing PERL_MM_OPT or PERL_MB_OPT.
   
-  Kills any existing PERL5LIB, PERL_MM_OPT or PERL_MB_OPT.
+  =item * Should probably auto-fixup CPAN config if not already done.
   
-  Should probably auto-fixup CPAN config if not already done.
+  =item * local::lib loads L<File::Spec>.  When used to set shell variables,
+  this isn't a problem.  When used inside a perl script, any L<File::Spec>
+  version inside the local::lib will be ignored.  A workaround for this is using
+  C<use lib "$ENV{HOME}/perl5/lib/perl5";> inside the script instead of using
+  C<local::lib> directly.
+  
+  =item * Conflicts with L<ExtUtils::MakeMaker>'s C<PREFIX> option.
+  C<local::lib> uses the C<INSTALL_BASE> option, as it has more predictable and
+  sane behavior.  If something attempts to use the C<PREFIX> option when running
+  a F<Makefile.PL>, L<ExtUtils::MakeMaker> will refuse to run, as the two
+  options conflict.  This can be worked around by temporarily unsetting the
+  C<PERL_MM_OPT> environment variable.
+  
+  =item * Conflicts with L<Module::Build>'s C<--prefix> option.  Similar to the
+  previous limitation, but any C<--prefix> option specified will be ignored.
+  This can be worked around by temporarily unsetting the C<PERL_MB_OPT>
+  environment variable.
+  
+  =back
   
   Patches very much welcome for any of the above.
   
-  On Win32 systems, does not have a way to write the created environment variables
-  to the registry, so that they can persist through a reboot.
+  =over 4
+  
+  =item * On Win32 systems, does not have a way to write the created environment
+  variables to the registry, so that they can persist through a reboot.
+  
+  =back
   
   =head1 TROUBLESHOOTING
   
@@ -20097,8 +20843,8 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   documentation additions, contributed by Christopher Nehren <apeiron@cpan.org>.
   
   Doc patches for a custom local::lib directory, more cleanups in the english
-  documentation and a L<german documentation|POD2::DE::local::lib> contributed by Torsten Raudssus
-  <torsten@raudssus.de>.
+  documentation and a L<german documentation|POD2::DE::local::lib> contributed by
+  Torsten Raudssus <torsten@raudssus.de>.
   
   Hans Dieter Pearcey <hdp@cpan.org> sent in some additional tests for ensuring
   things will install properly, submitted a fix for the bug causing problems with
@@ -20109,52 +20855,310 @@ $fatpacked{"local/lib.pm"} = <<'LOCAL_LIB';
   pattern of Freenode IRC contributed the beginnings of the Troubleshooting
   section. Many thanks!
   
-  Patch to add Win32 support contributed by Curtis Jewell <csjewell@cpan.org>.
+  Patch to add Win32 support contributed by Curtis Jewell <csjewell@cpan.org>.
+  
+  Warnings for missing PATH/PERL5LIB (as when not running interactively) silenced
+  by a patch from Marco Emilio Poleggi.
+  
+  Mark Stosberg <mark@summersault.com> provided the code for the now deleted
+  '--self-contained' option.
+  
+  Documentation patches to make win32 usage clearer by
+  David Mertens <dcmertens.perl@gmail.com> (run4flat).
+  
+  Brazilian L<portuguese translation|POD2::PT_BR::local::lib> and minor doc
+  patches contributed by Breno G. de Oliveira <garu@cpan.org>.
+  
+  Improvements to stacking multiple local::lib dirs and removing them from the
+  environment later on contributed by Andrew Rodland <arodland@cpan.org>.
+  
+  Patch for Carp version mismatch contributed by Hakim Cassimally
+  <osfameron@cpan.org>.
+  
+  Rewrite of internals and numerous bug fixes and added features contributed by
+  Graham Knop <haarg@haarg.org>.
+  
+  =head1 COPYRIGHT
+  
+  Copyright (c) 2007 - 2013 the local::lib L</AUTHOR> and L</CONTRIBUTORS> as
+  listed above.
+  
+  =head1 LICENSE
+  
+  This is free software; you can redistribute it and/or modify it under
+  the same terms as the Perl 5 programming language system itself.
+  
+  =cut
+LOCAL_LIB
+
+$fatpacked{"parent.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PARENT';
+  package parent;
+  use strict;
+  use vars qw($VERSION);
+  $VERSION = '0.225';
+  
+  sub import {
+      my $class = shift;
+  
+      my $inheritor = caller(0);
+  
+      if ( @_ and $_[0] eq '-norequire' ) {
+          shift @_;
+      } else {
+          for ( my @filename = @_ ) {
+              if ( $_ eq $inheritor ) {
+                  warn "Class '$inheritor' tried to inherit from itself\n";
+              };
+  
+              s{::|'}{/}g;
+              require "$_.pm"; # dies if the file is not found
+          }
+      }
+  
+      {
+          no strict 'refs';
+          push @{"$inheritor\::ISA"}, @_;
+      };
+  };
+  
+  "All your base are belong to us"
+  
+  __END__
+  
+  =encoding utf8
+  
+  =head1 NAME
+  
+  parent - Establish an ISA relationship with base classes at compile time
+  
+  =head1 SYNOPSIS
+  
+      package Baz;
+      use parent qw(Foo Bar);
+  
+  =head1 DESCRIPTION
+  
+  Allows you to both load one or more modules, while setting up inheritance from
+  those modules at the same time.  Mostly similar in effect to
+  
+      package Baz;
+      BEGIN {
+          require Foo;
+          require Bar;
+          push @ISA, qw(Foo Bar);
+      }
+  
+  By default, every base class needs to live in a file of its own.
+  If you want to have a subclass and its parent class in the same file, you
+  can tell C<parent> not to load any modules by using the C<-norequire> switch:
+  
+    package Foo;
+    sub exclaim { "I CAN HAS PERL" }
+  
+    package DoesNotLoadFooBar;
+    use parent -norequire, 'Foo', 'Bar';
+    # will not go looking for Foo.pm or Bar.pm
+  
+  This is equivalent to the following code:
+  
+    package Foo;
+    sub exclaim { "I CAN HAS PERL" }
+  
+    package DoesNotLoadFooBar;
+    push @DoesNotLoadFooBar::ISA, 'Foo', 'Bar';
+  
+  This is also helpful for the case where a package lives within
+  a differently named file:
+  
+    package MyHash;
+    use Tie::Hash;
+    use parent -norequire, 'Tie::StdHash';
+  
+  This is equivalent to the following code:
+  
+    package MyHash;
+    require Tie::Hash;
+    push @ISA, 'Tie::StdHash';
+  
+  If you want to load a subclass from a file that C<require> would
+  not consider an eligible filename (that is, it does not end in
+  either C<.pm> or C<.pmc>), use the following code:
+  
+    package MySecondPlugin;
+    require './plugins/custom.plugin'; # contains Plugin::Custom
+    use parent -norequire, 'Plugin::Custom';
+  
+  =head1 DIAGNOSTICS
+  
+  =over 4
+  
+  =item Class 'Foo' tried to inherit from itself
+  
+  Attempting to inherit from yourself generates a warning.
+  
+      package Foo;
+      use parent 'Foo';
+  
+  =back
+  
+  =head1 HISTORY
+  
+  This module was forked from L<base> to remove the cruft
+  that had accumulated in it.
+  
+  =head1 CAVEATS
+  
+  =head1 SEE ALSO
+  
+  L<base>
+  
+  =head1 AUTHORS AND CONTRIBUTORS
+  
+  Rafaël Garcia-Suarez, Bart Lateur, Max Maischein, Anno Siegel, Michael Schwern
+  
+  =head1 MAINTAINER
+  
+  Max Maischein C< corion@cpan.org >
+  
+  Copyright (c) 2007-10 Max Maischein C<< <corion@cpan.org> >>
+  Based on the idea of C<base.pm>, which was introduced with Perl 5.004_04.
+  
+  =head1 LICENSE
+  
+  This module is released under the same terms as Perl itself.
+  
+  =cut
+PARENT
+
+$fatpacked{"version.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION';
+  #!perl -w
+  package version;
+  
+  use 5.006002;
+  use strict;
+  
+  use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);
+  
+  $VERSION = 0.9908;
+  $CLASS = 'version';
+  
+  # !!!!Delete this next block completely when adding to Perl core!!!!
+  {
+      local $SIG{'__DIE__'};
+      eval "use version::vxs $VERSION";
+      if ( $@ ) { # don't have the XS version installed
+  	eval "use version::vpp $VERSION"; # don't tempt fate
+  	die "$@" if ( $@ );
+  	push @ISA, "version::vpp";
+  	local $^W;
+  	*version::qv = \&version::vpp::qv;
+  	*version::declare = \&version::vpp::declare;
+  	*version::_VERSION = \&version::vpp::_VERSION;
+  	*version::vcmp = \&version::vpp::vcmp;
+  	*version::new = \&version::vpp::new;
+  	if ($] >= 5.009000) {
+  	    no strict 'refs';
+  	    *version::stringify = \&version::vpp::stringify;
+  	    *{'version::(""'} = \&version::vpp::stringify;
+  	    *{'version::(<=>'} = \&version::vpp::vcmp;
+  	    *version::parse = \&version::vpp::parse;
+  	}
+      }
+      else { # use XS module
+  	push @ISA, "version::vxs";
+  	local $^W;
+  	*version::declare = \&version::vxs::declare;
+  	*version::qv = \&version::vxs::qv;
+  	*version::_VERSION = \&version::vxs::_VERSION;
+  	*version::vcmp = \&version::vxs::VCMP;
+  	*version::new = \&version::vxs::new;
+  	if ($] >= 5.009000) {
+  	    no strict 'refs';
+  	    *version::stringify = \&version::vxs::stringify;
+  	    *{'version::(""'} = \&version::vxs::stringify;
+  	    *{'version::(<=>'} = \&version::vxs::VCMP;
+  	    *version::parse = \&version::vxs::parse;
+  	}
+      }
+  }
+  
+  # avoid using Exporter
+  require version::regex;
+  *version::is_lax = \&version::regex::is_lax;
+  *version::is_strict = \&version::regex::is_strict;
+  *LAX = \$version::regex::LAX;
+  *STRICT = \$version::regex::STRICT;
   
-  Warnings for missing PATH/PERL5LIB (as when not running interactively) silenced
-  by a patch from Marco Emilio Poleggi.
+  sub import {
+      no strict 'refs';
+      my ($class) = shift;
   
-  Mark Stosberg <mark@summersault.com> provided the code for the now deleted
-  '--self-contained' option.
+      # Set up any derived class
+      unless ($class eq $CLASS) {
+  	local $^W;
+  	*{$class.'::declare'} =  \&{$CLASS.'::declare'};
+  	*{$class.'::qv'} = \&{$CLASS.'::qv'};
+      }
   
-  Documentation patches to make win32 usage clearer by
-  David Mertens <dcmertens.perl@gmail.com> (run4flat).
+      my %args;
+      if (@_) { # any remaining terms are arguments
+  	map { $args{$_} = 1 } @_
+      }
+      else { # no parameters at all on use line
+  	%args =
+  	(
+  	    qv => 1,
+  	    'UNIVERSAL::VERSION' => 1,
+  	);
+      }
   
-  Brazilian L<portuguese translation|POD2::PT_BR::local::lib> and minor doc patches contributed by Breno
-  G. de Oliveira <garu@cpan.org>.
+      my $callpkg = caller();
   
-  Improvements to stacking multiple local::lib dirs and removing them from the
-  environment later on contributed by Andrew Rodland <arodland@cpan.org>.
+      if (exists($args{declare})) {
+  	*{$callpkg.'::declare'} =
+  	    sub {return $class->declare(shift) }
+  	  unless defined(&{$callpkg.'::declare'});
+      }
   
-  Patch for Carp version mismatch contributed by Hakim Cassimally <osfameron@cpan.org>.
+      if (exists($args{qv})) {
+  	*{$callpkg.'::qv'} =
+  	    sub {return $class->qv(shift) }
+  	  unless defined(&{$callpkg.'::qv'});
+      }
   
-  =head1 COPYRIGHT
+      if (exists($args{'UNIVERSAL::VERSION'})) {
+  	local $^W;
+  	*UNIVERSAL::VERSION
+  		= \&{$CLASS.'::_VERSION'};
+      }
   
-  Copyright (c) 2007 - 2010 the local::lib L</AUTHOR> and L</CONTRIBUTORS> as
-  listed above.
+      if (exists($args{'VERSION'})) {
+  	*{$callpkg.'::VERSION'} = \&{$CLASS.'::_VERSION'};
+      }
   
-  =head1 LICENSE
+      if (exists($args{'is_strict'})) {
+  	*{$callpkg.'::is_strict'} = \&{$CLASS.'::is_strict'}
+  	  unless defined(&{$callpkg.'::is_strict'});
+      }
   
-  This library is free software and may be distributed under the same terms
-  as perl itself.
+      if (exists($args{'is_lax'})) {
+  	*{$callpkg.'::is_lax'} = \&{$CLASS.'::is_lax'}
+  	  unless defined(&{$callpkg.'::is_lax'});
+      }
+  }
   
-  =cut
   
   1;
-LOCAL_LIB
+VERSION
 
-$fatpacked{"version.pm"} = <<'VERSION';
-  #!perl -w
-  package version;
+$fatpacked{"version/regex.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION_REGEX';
+  package version::regex;
   
-  use 5.005_04;
   use strict;
   
-  use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);
-  
-  $VERSION = 0.9902;
+  use vars qw($VERSION $CLASS $STRICT $LAX);
   
-  $CLASS = 'version';
+  $VERSION = 0.9908;
   
   #--------------------------------------------------------------------------#
   # Version regexp components
@@ -20260,112 +21264,14 @@ $fatpacked{"version.pm"} = <<'VERSION';
   
   #--------------------------------------------------------------------------#
   
-  {
-      local $SIG{'__DIE__'};
-      eval "use version::vxs $VERSION";
-      if ( $@ ) { # don't have the XS version installed
-  	eval "use version::vpp $VERSION"; # don't tempt fate
-  	die "$@" if ( $@ );
-  	push @ISA, "version::vpp";
-  	local $^W;
-  	*version::qv = \&version::vpp::qv;
-  	*version::declare = \&version::vpp::declare;
-  	*version::_VERSION = \&version::vpp::_VERSION;
-  	*version::vcmp = \&version::vpp::vcmp;
-  	*version::new = \&version::vpp::new;
-  	if ($] >= 5.009000) {
-  	    no strict 'refs';
-  	    *version::stringify = \&version::vpp::stringify;
-  	    *{'version::(""'} = \&version::vpp::stringify;
-  	    *{'version::(<=>'} = \&version::vpp::vcmp;
-  	    *version::parse = \&version::vpp::parse;
-  	}
-      }
-      else { # use XS module
-  	push @ISA, "version::vxs";
-  	local $^W;
-  	*version::declare = \&version::vxs::declare;
-  	*version::qv = \&version::vxs::qv;
-  	*version::_VERSION = \&version::vxs::_VERSION;
-  	*version::vcmp = \&version::vxs::VCMP;
-  	*version::new = \&version::vxs::new;
-  	if ($] >= 5.009000) {
-  	    no strict 'refs';
-  	    *version::stringify = \&version::vxs::stringify;
-  	    *{'version::(""'} = \&version::vxs::stringify;
-  	    *{'version::(<=>'} = \&version::vxs::VCMP;
-  	    *version::parse = \&version::vxs::parse;
-  	}
-  
-      }
-  }
-  
   # Preloaded methods go here.
-  sub import {
-      no strict 'refs';
-      my ($class) = shift;
-  
-      # Set up any derived class
-      unless ($class eq 'version') {
-  	local $^W;
-  	*{$class.'::declare'} =  \&version::declare;
-  	*{$class.'::qv'} = \&version::qv;
-      }
-  
-      my %args;
-      if (@_) { # any remaining terms are arguments
-  	map { $args{$_} = 1 } @_
-      }
-      else { # no parameters at all on use line
-      	%args = 
-  	(
-  	    qv => 1,
-  	    'UNIVERSAL::VERSION' => 1,
-  	);
-      }
-  
-      my $callpkg = caller();
-      
-      if (exists($args{declare})) {
-  	*{$callpkg.'::declare'} = 
-  	    sub {return $class->declare(shift) }
-  	  unless defined(&{$callpkg.'::declare'});
-      }
-  
-      if (exists($args{qv})) {
-  	*{$callpkg.'::qv'} =
-  	    sub {return $class->qv(shift) }
-  	  unless defined(&{$callpkg.'::qv'});
-      }
-  
-      if (exists($args{'UNIVERSAL::VERSION'})) {
-  	local $^W;
-  	*UNIVERSAL::VERSION 
-  		= \&version::_VERSION;
-      }
-  
-      if (exists($args{'VERSION'})) {
-  	*{$callpkg.'::VERSION'} = \&version::_VERSION;
-      }
-  
-      if (exists($args{'is_strict'})) {
-  	*{$callpkg.'::is_strict'} = \&version::is_strict
-  	  unless defined(&{$callpkg.'::is_strict'});
-      }
-  
-      if (exists($args{'is_lax'})) {
-  	*{$callpkg.'::is_lax'} = \&version::is_lax
-  	  unless defined(&{$callpkg.'::is_lax'});
-      }
-  }
-  
   sub is_strict	{ defined $_[0] && $_[0] =~ qr/ \A $STRICT \z /x }
   sub is_lax	{ defined $_[0] && $_[0] =~ qr/ \A $LAX \z /x }
   
   1;
-VERSION
+VERSION_REGEX
 
-$fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
+$fatpacked{"version/vpp.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'VERSION_VPP';
   package charstar;
   # a little helper class to emulate C char* semantics in Perl
   # so that prescan_version can use the same code as in C
@@ -20484,12 +21390,20 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
   }
   
   package version::vpp;
+  
+  use 5.006002;
   use strict;
   
-  use POSIX qw/locale_h/;
-  use locale;
-  use vars qw ($VERSION @ISA @REGEXS);
-  $VERSION = 0.9902;
+  use Config;
+  use vars qw($VERSION $CLASS @ISA $LAX $STRICT);
+  $VERSION = 0.9908;
+  $CLASS = 'version::vpp';
+  
+  require version::regex;
+  *version::vpp::is_strict = \&version::regex::is_strict;
+  *version::vpp::is_lax = \&version::regex::is_lax;
+  *LAX = \$version::regex::LAX;
+  *STRICT = \$version::regex::STRICT;
   
   use overload (
       '""'       => \&stringify,
@@ -20518,6 +21432,64 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
       ';
   }
   
+  sub import {
+      no strict 'refs';
+      my ($class) = shift;
+  
+      # Set up any derived class
+      unless ($class eq $CLASS) {
+  	local $^W;
+  	*{$class.'::declare'} =  \&{$CLASS.'::declare'};
+  	*{$class.'::qv'} = \&{$CLASS.'::qv'};
+      }
+  
+      my %args;
+      if (@_) { # any remaining terms are arguments
+  	map { $args{$_} = 1 } @_
+      }
+      else { # no parameters at all on use line
+  	%args =
+  	(
+  	    qv => 1,
+  	    'UNIVERSAL::VERSION' => 1,
+  	);
+      }
+  
+      my $callpkg = caller();
+  
+      if (exists($args{declare})) {
+  	*{$callpkg.'::declare'} =
+  	    sub {return $class->declare(shift) }
+  	  unless defined(&{$callpkg.'::declare'});
+      }
+  
+      if (exists($args{qv})) {
+  	*{$callpkg.'::qv'} =
+  	    sub {return $class->qv(shift) }
+  	  unless defined(&{$callpkg.'::qv'});
+      }
+  
+      if (exists($args{'UNIVERSAL::VERSION'})) {
+  	local $^W;
+  	*UNIVERSAL::VERSION
+  		= \&{$CLASS.'::_VERSION'};
+      }
+  
+      if (exists($args{'VERSION'})) {
+  	*{$callpkg.'::VERSION'} = \&{$CLASS.'::_VERSION'};
+      }
+  
+      if (exists($args{'is_strict'})) {
+  	*{$callpkg.'::is_strict'} = \&{$CLASS.'::is_strict'}
+  	  unless defined(&{$callpkg.'::is_strict'});
+      }
+  
+      if (exists($args{'is_lax'})) {
+  	*{$callpkg.'::is_lax'} = \&{$CLASS.'::is_lax'}
+  	  unless defined(&{$callpkg.'::is_lax'});
+      }
+  }
+  
   my $VERSION_MAX = 0x7FFFFFFF;
   
   # implement prescan_version as closely to the C version as possible
@@ -20780,7 +21752,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
       if ($errstr) {
   	# 'undef' is a special case and not an error
   	if ( $s ne 'undef') {
-  	    use Carp;
+  	    require Carp;
   	    Carp::croak($errstr);
   	}
       }
@@ -20936,25 +21908,49 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
       return $s;
   }
   
-  sub new
-  {
-  	my ($class, $value) = @_;
-  	unless (defined $class) {
-  	    require Carp;
-  	    Carp::croak('Usage: version::new(class, version)');
-  	}
-  	my $self = bless ({}, ref ($class) || $class);
-  	my $qv = FALSE;
-  
-  	if ( ref($value) && eval('$value->isa("version")') ) {
-  	    # Can copy the elements directly
-  	    $self->{version} = [ @{$value->{version} } ];
-  	    $self->{qv} = 1 if $value->{qv};
-  	    $self->{alpha} = 1 if $value->{alpha};
-  	    $self->{original} = ''.$value->{original};
-  	    return $self;
-  	}
+  sub new {
+      my $class = shift;
+      unless (defined $class or $#_ > 1) {
+  	require Carp;
+  	Carp::croak('Usage: version::new(class, version)');
+      }
+  
+      my $self = bless ({}, ref ($class) || $class);
+      my $qv = FALSE;
+  
+      if ( $#_ == 1 ) { # must be CVS-style
+  	$qv = TRUE;
+      }
+      my $value = pop; # always going to be the last element
+  
+      if ( ref($value) && eval('$value->isa("version")') ) {
+  	# Can copy the elements directly
+  	$self->{version} = [ @{$value->{version} } ];
+  	$self->{qv} = 1 if $value->{qv};
+  	$self->{alpha} = 1 if $value->{alpha};
+  	$self->{original} = ''.$value->{original};
+  	return $self;
+      }
+  
+      if ( not defined $value or $value =~ /^undef$/ ) {
+  	# RT #19517 - special case for undef comparison
+  	# or someone forgot to pass a value
+  	push @{$self->{version}}, 0;
+  	$self->{original} = "0";
+  	return ($self);
+      }
+  
+  
+      if (ref($value) =~ m/ARRAY|HASH/) {
+  	require Carp;
+  	Carp::croak("Invalid version format (non-numeric data)");
+      }
+  
+      $value = _un_vstring($value);
   
+      if ($Config{d_setlocale}) {
+  	use POSIX qw/locale_h/;
+  	use if $Config{d_setlocale}, 'locale';
   	my $currlocale = setlocale(LC_ALL);
   
   	# if the current locale uses commas for decimal points, we
@@ -20963,42 +21959,27 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
   	if ( localeconv()->{decimal_point} eq ',' ) {
   	    $value =~ tr/,/./;
   	}
+      }
   
-  	if ( not defined $value or $value =~ /^undef$/ ) {
-  	    # RT #19517 - special case for undef comparison
-  	    # or someone forgot to pass a value
-  	    push @{$self->{version}}, 0;
-  	    $self->{original} = "0";
-  	    return ($self);
-  	}
-  
-  	if ( $#_ == 2 ) { # must be CVS-style
-  	    $value = $_[2];
-  	    $qv = TRUE;
-  	}
-  
-  	$value = _un_vstring($value);
-  
-  	# exponential notation
-  	if ( $value =~ /\d+.?\d*e[-+]?\d+/ ) {
-  	    $value = sprintf("%.9f",$value);
-  	    $value =~ s/(0+)$//; # trim trailing zeros
-  	}
+      # exponential notation
+      if ( $value =~ /\d+.?\d*e[-+]?\d+/ ) {
+  	$value = sprintf("%.9f",$value);
+  	$value =~ s/(0+)$//; # trim trailing zeros
+      }
   
-  	my $s = scan_version($value, \$self, $qv);
+      my $s = scan_version($value, \$self, $qv);
   
-  	if ($s) { # must be something left over
-  	    warn("Version string '%s' contains invalid data; "
-                         ."ignoring: '%s'", $value, $s);
-  	}
+      if ($s) { # must be something left over
+  	warn("Version string '%s' contains invalid data; "
+  		   ."ignoring: '%s'", $value, $s);
+      }
   
-  	return ($self);
+      return ($self);
   }
   
   *parse = \&new;
   
-  sub numify
-  {
+  sub numify {
       my ($self) = @_;
       unless (_verify($self)) {
   	require Carp;
@@ -21038,8 +22019,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
       return $string;
   }
   
-  sub normal
-  {
+  sub normal {
       my ($self) = @_;
       unless (_verify($self)) {
   	require Carp;
@@ -21074,8 +22054,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
       return $string;
   }
   
-  sub stringify
-  {
+  sub stringify {
       my ($self) = @_;
       unless (_verify($self)) {
   	require Carp;
@@ -21088,8 +22067,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
   	    : $self->numify;
   }
   
-  sub vcmp
-  {
+  sub vcmp {
       require UNIVERSAL;
       my ($left,$right,$swap) = @_;
       my $class = ref($left);
@@ -21174,7 +22152,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
   
   sub qv {
       my $value = shift;
-      my $class = 'version';
+      my $class = $CLASS;
       if (@_) {
   	$class = ref($value) || $value;
   	$value = shift;
@@ -21182,7 +22160,7 @@ $fatpacked{"version/vpp.pm"} = <<'VERSION_VPP';
   
       $value = _un_vstring($value);
       $value = 'v'.$value unless $value =~ /(^v|\d+\.\d+\.\d)/;
-      my $obj = version->new($value);
+      my $obj = $CLASS->new($value);
       return bless $obj, $class;
   }
   
@@ -21321,24 +22299,37 @@ VERSION_VPP
 
 s/^  //mg for values %fatpacked;
 
-unshift @INC, sub {
-  if (my $fat = $fatpacked{$_[1]}) {
-    if ($] < 5.008) {
-      return sub {
-        return 0 unless length $fat;
-        $fat =~ s/^([^\n]*\n?)//;
-        $_ = $1;
-        return 1;
-      };
+my $class = 'FatPacked::'.(0+\%fatpacked);
+no strict 'refs';
+*{"${class}::files"} = sub { keys %{$_[0]} };
+
+if ($] < 5.008) {
+  *{"${class}::INC"} = sub {
+     if (my $fat = $_[0]{$_[1]}) {
+       return sub {
+         return 0 unless length $fat;
+         $fat =~ s/^([^\n]*\n?)//;
+         $_ = $1;
+         return 1;
+       };
+     }
+     return;
+  };
+}
+
+else {
+  *{"${class}::INC"} = sub {
+    if (my $fat = $_[0]{$_[1]}) {
+      open my $fh, '<', \$fat
+        or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
+      return $fh;
     }
-    open my $fh, '<', \$fat
-      or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
-    return $fh;
-  }
-  return
-};
+    return;
+  };
+}
 
-} # END OF FATPACK CODE
+unshift @INC, bless \%fatpacked, $class;
+  } # END OF FATPACK CODE
 
 
 
@@ -1,5 +1,5 @@
 package App::cpanminus;
-our $VERSION = "1.7001";
+our $VERSION = "1.7004";
 
 =encoding utf8