comparison slide-cr.fatpack.pl @ 52:73b27e5c1d79 default tip

auto-Update generated slides by script
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Tue, 16 Apr 2019 18:58:24 +0900
parents ccfc78c23c66
children
comparison
equal deleted inserted replaced
51:5f949b153f65 52:73b27e5c1d79
1 #!/usr/bin/env perl
2
3 # This chunk of stuff was generated by App::FatPacker. To find the original
4 # file's code, look for the end of this BEGIN block or the string 'FATPACK'
5 BEGIN {
6 my %fatpacked;
7
8 $fatpacked{"CLI.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CLI';
9 package CLI;use strict;use warnings;use utf8;use Smart::Options;use Smart::Options::Declare;use Time::Piece;use Time::Seconds;use Capture::Tiny qw/capture/;use Path::Tiny;use File::chdir;use Carp qw/croak/;use Class::Tiny qw/template root_dir/;use feature 'say';sub run {my($self,@args)=@_;my$opt=Smart::Options->new->options(file=>{describe=>'target file',alias=>'f'});$opt->subcmd(new=>Smart::Options->new(),build=>Smart::Options->new(),open=>Smart::Options->new->default('target'=>'slide.md'),build_open=>Smart::Options->new->default('target'=>'slide.md'),upload=>Smart::Options->new(),memo=>Smart::Options->new(),edit=>Smart::Options->new(),zip=>Smart::Options->new(),);my$result=$opt->parse(@args);my$command=$result->{command}// "open";my$option=$result->{cmd_option}->{f}|| $result->{cmd_option}->{file}|| 0;my$call=$self->can("cmd_$command");croak 'undefine subcommand' unless$call;$self->$call($option)}sub cmd_new {my ($self)=@_;my ($y,$m,$d)=_y_m_d();my$slide=path($self->root_dir)->child($y)->child($m)->child($d)->child('slide.md')->touchpath;path($self->template)->copy($slide)}sub cmd_build {my($self,$target)=@_;if ($target){$target=path($target);$self->_build($target->dirname,$target->basename)}else {$self->_build($self->_search_recently_day())}}sub _build {my ($self,$dir,$target)=@_;$target //= 'slide.md';say "[AUTO] BUILD at $dir/$target";local$CWD=$dir;my ($stdout,$stderr,$exit)=capture {system("slideshow build ${target} -t s6cr")};croak "Perl can't build...." if$stderr}sub cmd_build_open {my($self,$target)=@_;$self->cmd_build($target);if($target){$target =~ s/\.md$/\.html/}else {my@targets=$self->_search_recently_day()->children(qr/(?<!pdf)\.html$/);$target=pop@targets}$self->cmd_open(path($target))}sub cmd_open {my($self,$slide)=@_;my$target;if ($slide){$target=$slide}else {$slide='slide.html';$target=$self->_search_recently_day()->child($slide)}if($target->realpath){system 'open',($target->realpath)}else {croak 'dont found slide.html'}}sub cmd_upload {say "[AUTO]hg addremove";my ($stdout,$stderr,$exit)=capture {system("hg addremove");system("hg add")};croak "didn't add" if$stderr;say "[AUTO]hg commit -m auto-Update generated slides by script";($stdout,$stderr,$exit)=capture {system('hg commit -m "auto-Update generated slides by script"')};if ($stderr){say$stderr;croak "didn't commit"}say "[AUTO]hg push";($stdout,$stderr,$exit)=capture {system('hg push')};if ($stderr){say$stderr;croak "didn't commit"}else {say$stdout}}sub _y_m_d {my$t=localtime;($t->strftime('%Y'),$t->strftime('%m'),$t->strftime('%d'))}sub _search_recently_day {my ($self)=@_;my ($y,$m,$d)=_y_m_d();my$root_dir=path($self->root_dir)->child($y)->child($m);my$date=shift @{[sort {$b->stat->mtime <=> $a->stat->mtime}$root_dir->children]};return$date}sub cmd_memo {my ($self)=@_;my ($y,$m,$d)=_y_m_d();my$memo=path($self->root_dir)->child($y)->child($m)->child($d)->child('memo.txt')->touchpath;exec$ENV{EDITOR},($memo->realpath)}sub cmd_edit {my ($self)=@_;my$recent_day=$self->_search_recently_day();my@targets=$recent_day->children(qr/\.md$/);my$target=pop@targets;exec$ENV{EDITOR},($target->realpath)}sub cmd_zip {my ($self)=@_;my$recent_day=$self->_search_recently_day();my$t=localtime;my$zip=$recent_day->child('zip.txt')->touch->opena;$t-= ONE_WEEK;for(0..7){my($y,$m,$d)=($t->strftime('%Y'),$t->strftime('%m'),$t->strftime('%d'));my$memo=path($self->root_dir)->child($y)->child($m)->child($d)->child('memo.txt');unless ($memo->exists){$t += ONE_DAY;next}say$zip "$y-$m-$d----";say$zip $memo->slurp;say$zip "----------";$t += ONE_DAY}}1;
10 CLI
11
12 $fatpacked{"Capture/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CAPTURE_TINY';
13 use 5.006;use strict;use warnings;package Capture::Tiny;our$VERSION='0.48';use Carp ();use Exporter ();use IO::Handle ();use File::Spec ();use File::Temp qw/tempfile tmpnam/;use Scalar::Util qw/reftype blessed/;BEGIN {local $@;eval {require PerlIO;PerlIO->can('get_layers')}or *PerlIO::get_layers=sub {return ()}}my%api=(capture=>[1,1,0,0],capture_stdout=>[1,0,0,0],capture_stderr=>[0,1,0,0],capture_merged=>[1,1,1,0],tee=>[1,1,0,1],tee_stdout=>[1,0,0,1],tee_stderr=>[0,1,0,1],tee_merged=>[1,1,1,1],);for my$sub (keys%api){my$args=join q{, },@{$api{$sub}};eval "sub $sub(&;@) {unshift \@_, $args; goto \\&_capture_tee;}"}our@ISA=qw/Exporter/;our@EXPORT_OK=keys%api;our%EXPORT_TAGS=('all'=>\@EXPORT_OK);my$IS_WIN32=$^O eq 'MSWin32';our$TIMEOUT=30;my@cmd=($^X,'-C0','-e',<<'HERE');sub _relayer {my ($fh,$apply_layers)=@_;binmode($fh,":raw");while (1 < (my$layers=()=PerlIO::get_layers($fh,output=>1))){binmode($fh,":pop")}my@to_apply=@$apply_layers;shift@to_apply;binmode($fh,":" .join(":",@to_apply))}sub _name {my$glob=shift;no strict 'refs';return *{$glob}{NAME}}sub _open {open $_[0],$_[1]or Carp::confess "Error from open(" .join(q{, },@_)."): $!"}sub _close {close $_[0]or Carp::confess "Error from close(" .join(q{, },@_)."): $!"}my%dup;my%proxy_count;sub _proxy_std {my%proxies;if (!defined fileno STDIN){$proxy_count{stdin}++;if (defined$dup{stdin}){_open \*STDIN,"<&=" .fileno($dup{stdin})}else {_open \*STDIN,"<" .File::Spec->devnull;_open$dup{stdin}=IO::Handle->new,"<&=STDIN"}$proxies{stdin}=\*STDIN;binmode(STDIN,':utf8')if $] >= 5.008}if (!defined fileno STDOUT){$proxy_count{stdout}++;if (defined$dup{stdout}){_open \*STDOUT,">&=" .fileno($dup{stdout})}else {_open \*STDOUT,">" .File::Spec->devnull;_open$dup{stdout}=IO::Handle->new,">&=STDOUT"}$proxies{stdout}=\*STDOUT;binmode(STDOUT,':utf8')if $] >= 5.008}if (!defined fileno STDERR){$proxy_count{stderr}++;if (defined$dup{stderr}){_open \*STDERR,">&=" .fileno($dup{stderr})}else {_open \*STDERR,">" .File::Spec->devnull;_open$dup{stderr}=IO::Handle->new,">&=STDERR"}$proxies{stderr}=\*STDERR;binmode(STDERR,':utf8')if $] >= 5.008}return%proxies}sub _unproxy {my (%proxies)=@_;for my$p (keys%proxies){$proxy_count{$p}--;if (!$proxy_count{$p}){_close$proxies{$p};_close$dup{$p}unless $] < 5.008;delete$dup{$p}}}}sub _copy_std {my%handles;for my$h (qw/stdout stderr stdin/){next if$h eq 'stdin' &&!$IS_WIN32;my$redir=$h eq 'stdin' ? "<&" : ">&";_open$handles{$h}=IO::Handle->new(),$redir .uc($h)}return \%handles}sub _open_std {my ($handles)=@_;_open \*STDIN,"<&" .fileno$handles->{stdin}if defined$handles->{stdin};_open \*STDOUT,">&" .fileno$handles->{stdout}if defined$handles->{stdout};_open \*STDERR,">&" .fileno$handles->{stderr}if defined$handles->{stderr}}sub _start_tee {my ($which,$stash)=@_;$stash->{$_}{$which}=IO::Handle->new for qw/tee reader/;pipe$stash->{reader}{$which},$stash->{tee}{$which};select((select($stash->{tee}{$which}),$|=1)[0]);$stash->{new}{$which}=$stash->{tee}{$which};$stash->{child}{$which}={stdin=>$stash->{reader}{$which},stdout=>$stash->{old}{$which},stderr=>$stash->{capture}{$which},};$stash->{flag_files}{$which}=scalar(tmpnam()).$$;if ($IS_WIN32){my$old_eval_err=$@;undef $@;eval "use Win32API::File qw/GetOsFHandle SetHandleInformation fileLastError HANDLE_FLAG_INHERIT INVALID_HANDLE_VALUE/ ";my$os_fhandle=GetOsFHandle($stash->{tee}{$which});my$result=SetHandleInformation($os_fhandle,HANDLE_FLAG_INHERIT(),0);_open_std($stash->{child}{$which});$stash->{pid}{$which}=system(1,@cmd,$stash->{flag_files}{$which});$@=$old_eval_err}else {_fork_exec($which,$stash)}}sub _fork_exec {my ($which,$stash)=@_;my$pid=fork;if (not defined$pid){Carp::confess "Couldn't fork(): $!"}elsif ($pid==0){untie*STDIN;untie*STDOUT;untie*STDERR;_close$stash->{tee}{$which};_open_std($stash->{child}{$which});exec@cmd,$stash->{flag_files}{$which}}$stash->{pid}{$which}=$pid}my$have_usleep=eval "use Time::HiRes 'usleep'; 1";sub _files_exist {return 1 if @_==grep {-f}@_;Time::HiRes::usleep(1000)if$have_usleep;return 0}sub _wait_for_tees {my ($stash)=@_;my$start=time;my@files=values %{$stash->{flag_files}};my$timeout=defined$ENV{PERL_CAPTURE_TINY_TIMEOUT}? $ENV{PERL_CAPTURE_TINY_TIMEOUT}: $TIMEOUT;1 until _files_exist(@files)|| ($timeout && (time - $start > $timeout));Carp::confess "Timed out waiting for subprocesses to start" if!_files_exist(@files);unlink $_ for@files}sub _kill_tees {my ($stash)=@_;if ($IS_WIN32){close($_)for values %{$stash->{tee}};my$start=time;1 until wait==-1 || (time - $start > 30)}else {_close $_ for values %{$stash->{tee}};waitpid $_,0 for values %{$stash->{pid}}}}sub _slurp {my ($name,$stash)=@_;my ($fh,$pos)=map {$stash->{$_}{$name}}qw/capture pos/;seek($fh,$pos,0)or die "Couldn't seek on capture handle for $name\n";my$text=do {local $/;scalar readline$fh};return defined($text)? $text : ""}sub _capture_tee {my ($do_stdout,$do_stderr,$do_merge,$do_tee,$code,@opts)=@_;my%do=($do_stdout ? (stdout=>1): (),$do_stderr ? (stderr=>1): ());Carp::confess("Custom capture options must be given as key/value pairs\n")unless@opts % 2==0;my$stash={capture=>{@opts }};for (keys %{$stash->{capture}}){my$fh=$stash->{capture}{$_};Carp::confess "Custom handle for $_ must be seekable\n" unless ref($fh)eq 'GLOB' || (blessed($fh)&& $fh->isa("IO::Seekable"))}local*CT_ORIG_STDIN=*STDIN ;local*CT_ORIG_STDOUT=*STDOUT;local*CT_ORIG_STDERR=*STDERR;my%layers=(stdin=>[PerlIO::get_layers(\*STDIN)],stdout=>[PerlIO::get_layers(\*STDOUT,output=>1)],stderr=>[PerlIO::get_layers(\*STDERR,output=>1)],);$layers{stdout}=[PerlIO::get_layers(tied*STDOUT)]if tied(*STDOUT)&& (reftype tied*STDOUT eq 'GLOB');$layers{stderr}=[PerlIO::get_layers(tied*STDERR)]if tied(*STDERR)&& (reftype tied*STDERR eq 'GLOB');my%localize;$localize{stdin}++,local(*STDIN)if grep {$_ eq 'scalar'}@{$layers{stdin}};$localize{stdout}++,local(*STDOUT)if$do_stdout && grep {$_ eq 'scalar'}@{$layers{stdout}};$localize{stderr}++,local(*STDERR)if ($do_stderr || $do_merge)&& grep {$_ eq 'scalar'}@{$layers{stderr}};$localize{stdin}++,local(*STDIN),_open(\*STDIN,"<&=0")if tied*STDIN && $] >= 5.008;$localize{stdout}++,local(*STDOUT),_open(\*STDOUT,">&=1")if$do_stdout && tied*STDOUT && $] >= 5.008;$localize{stderr}++,local(*STDERR),_open(\*STDERR,">&=2")if ($do_stderr || $do_merge)&& tied*STDERR && $] >= 5.008;my%proxy_std=_proxy_std();$layers{stdout}=[PerlIO::get_layers(\*STDOUT,output=>1)]if$proxy_std{stdout};$layers{stderr}=[PerlIO::get_layers(\*STDERR,output=>1)]if$proxy_std{stderr};$stash->{old}=_copy_std();$stash->{new}={%{$stash->{old}}};for (keys%do){$stash->{new}{$_}=($stash->{capture}{$_}||= File::Temp->new);seek($stash->{capture}{$_},0,2)or die "Could not seek on capture handle for $_\n";$stash->{pos}{$_}=tell$stash->{capture}{$_};_start_tee($_=>$stash)if$do_tee}_wait_for_tees($stash)if$do_tee;$stash->{new}{stderr}=$stash->{new}{stdout}if$do_merge;_open_std($stash->{new});my ($exit_code,$inner_error,$outer_error,$orig_pid,@result);{$orig_pid=$$;local*STDIN=*CT_ORIG_STDIN if$localize{stdin};_relayer(\*STDOUT,$layers{stdout})if$do_stdout;_relayer(\*STDERR,$layers{stderr})if$do_stderr;my$old_eval_err=$@;undef $@;eval {@result=$code->();$inner_error=$@};$exit_code=$?;$outer_error=$@;STDOUT->flush if$do_stdout;STDERR->flush if$do_stderr;$@=$old_eval_err}_open_std($stash->{old});_close($_)for values %{$stash->{old}};_relayer(\*STDOUT,$layers{stdout})if$do_stdout;_relayer(\*STDERR,$layers{stderr})if$do_stderr;_unproxy(%proxy_std);_kill_tees($stash)if$do_tee;my%got;if ($orig_pid==$$ and (defined wantarray or ($do_tee && keys%localize))){for (keys%do){_relayer($stash->{capture}{$_},$layers{$_});$got{$_}=_slurp($_,$stash)}print CT_ORIG_STDOUT$got{stdout}if$do_stdout && $do_tee && $localize{stdout};print CT_ORIG_STDERR$got{stderr}if$do_stderr && $do_tee && $localize{stderr}}$?=$exit_code;$@=$inner_error if$inner_error;die$outer_error if$outer_error;return unless defined wantarray;my@return;push@return,$got{stdout}if$do_stdout;push@return,$got{stderr}if$do_stderr &&!$do_merge;push@return,@result;return wantarray ? @return : $return[0]}1;
14 use Fcntl;
15 $SIG{HUP}=sub{exit};
16 if ( my $fn=shift ) {
17 sysopen(my $fh, qq{$fn}, O_WRONLY|O_CREAT|O_EXCL) or die $!;
18 print {$fh} $$;
19 close $fh;
20 }
21 my $buf; while (sysread(STDIN, $buf, 2048)) {
22 syswrite(STDOUT, $buf); syswrite(STDERR, $buf);
23 }
24 HERE
25 CAPTURE_TINY
26
27 $fatpacked{"Class/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'CLASS_TINY';
28 use 5.006;use strict;no strict 'refs';use warnings;package Class::Tiny;our$VERSION='1.006';use Carp ();require($] >= 5.010 ? "mro.pm" : "MRO/Compat.pm");my%CLASS_ATTRIBUTES;sub import {my$class=shift;my$pkg=caller;$class->prepare_class($pkg);$class->create_attributes($pkg,@_)if @_}sub prepare_class {my ($class,$pkg)=@_;@{"${pkg}::ISA"}="Class::Tiny::Object" unless @{"${pkg}::ISA"}}sub create_attributes {my ($class,$pkg,@spec)=@_;my%defaults=map {ref $_ eq 'HASH' ? %$_ : ($_=>undef)}@spec;my@attr=grep {defined and!ref and /^[^\W\d]\w*$/s or Carp::croak "Invalid accessor name '$_'"}keys%defaults;$CLASS_ATTRIBUTES{$pkg}{$_}=$defaults{$_}for@attr;$class->_gen_accessor($pkg,$_)for grep {!*{"$pkg\::$_"}{CODE}}@attr;Carp::croak("Failed to generate attributes for $pkg: $@\n")if $@}sub _gen_accessor {my ($class,$pkg,$name)=@_;my$outer_default=$CLASS_ATTRIBUTES{$pkg}{$name};my$sub=$class->__gen_sub_body($name,defined($outer_default),ref($outer_default));eval "package $pkg; my \$default=\$outer_default; $sub";Carp::croak("Failed to generate attributes for $pkg: $@\n")if $@}sub __gen_sub_body {my ($self,$name,$has_default,$default_type)=@_;if ($has_default && $default_type eq 'CODE'){return << "HERE"}elsif ($has_default){return << "HERE"}else {return << "HERE"}}sub get_all_attributes_for {my ($class,$pkg)=@_;my%attr=map {$_=>undef}map {keys %{$CLASS_ATTRIBUTES{$_}|| {}}}@{mro::get_linear_isa($pkg)};return keys%attr}sub get_all_attribute_defaults_for {my ($class,$pkg)=@_;my$defaults={};for my$p (reverse @{mro::get_linear_isa($pkg)}){while (my ($k,$v)=each %{$CLASS_ATTRIBUTES{$p}|| {}}){$defaults->{$k}=$v}}return$defaults}package Class::Tiny::Object;our$VERSION='1.006';my (%HAS_BUILDARGS,%BUILD_CACHE,%DEMOLISH_CACHE,%ATTR_CACHE);my$_PRECACHE=sub {no warnings 'once';my ($class)=@_;my$linear_isa=@{"$class\::ISA"}==1 && ${"$class\::ISA"}[0]eq "Class::Tiny::Object" ? [$class]: mro::get_linear_isa($class);$DEMOLISH_CACHE{$class}=[map {(*{$_}{CODE})? (*{$_}{CODE}): ()}map {"$_\::DEMOLISH"}@$linear_isa ];$BUILD_CACHE{$class}=[map {(*{$_}{CODE})? (*{$_}{CODE}): ()}map {"$_\::BUILD"}reverse @$linear_isa ];$HAS_BUILDARGS{$class}=$class->can("BUILDARGS");return$ATTR_CACHE{$class}={map {$_=>1}Class::Tiny->get_all_attributes_for($class)}};sub new {my$class=shift;my$valid_attrs=$ATTR_CACHE{$class}|| $_PRECACHE->($class);my$args;if ($HAS_BUILDARGS{$class}){$args=$class->BUILDARGS(@_)}else {if (@_==1 && ref $_[0]){my%copy=eval {%{$_[0]}};Carp::croak("Argument to $class->new() could not be dereferenced as a hash")if $@;$args=\%copy}elsif (@_ % 2==0){$args={@_}}else {Carp::croak("$class->new() got an odd number of elements")}}my$self=bless {map {$_=>$args->{$_}}grep {exists$valid_attrs->{$_}}keys %$args },$class;$self->BUILDALL($args)if!delete$args->{__no_BUILD__}&& @{$BUILD_CACHE{$class}};return$self}sub BUILDALL {$_->(@_)for @{$BUILD_CACHE{ref $_[0]}}}require Devel::GlobalDestruction unless defined ${^GLOBAL_PHASE};sub DESTROY {my$self=shift;my$class=ref$self;my$in_global_destruction=defined ${^GLOBAL_PHASE} ? ${^GLOBAL_PHASE} eq 'DESTRUCT' : Devel::GlobalDestruction::in_global_destruction();for my$demolisher (@{$DEMOLISH_CACHE{$class}}){my$e=do {local ($?,$@);eval {$demolisher->($self,$in_global_destruction)};$@};no warnings 'misc';die$e if$e}}1;
29 sub $name {
30 return (
31 ( \@_ == 1 && exists \$_[0]{$name} )
32 ? ( \$_[0]{$name} )
33 : ( \$_[0]{$name} = ( \@_ == 2 ) ? \$_[1] : \$default->( \$_[0] ) )
34 );
35 }
36 HERE
37 sub $name {
38 return (
39 ( \@_ == 1 && exists \$_[0]{$name} )
40 ? ( \$_[0]{$name} )
41 : ( \$_[0]{$name} = ( \@_ == 2 ) ? \$_[1] : \$default )
42 );
43 }
44 HERE
45 sub $name {
46 return \@_ == 1 ? \$_[0]{$name} : ( \$_[0]{$name} = \$_[1] );
47 }
48 HERE
49 CLASS_TINY
50
51 $fatpacked{"Exporter/Shiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_SHINY';
52 package Exporter::Shiny;use 5.006001;use strict;use warnings;use Exporter::Tiny ();our$AUTHORITY='cpan:TOBYINK';our$VERSION='1.000000';sub import {my$me=shift;my$caller=caller;(my$nominal_file=$caller)=~ s(::)(/)g;$INC{"$nominal_file\.pm"}||= __FILE__;if (@_==2 and $_[0]eq -setup){my (undef,$opts)=@_;@_=@{delete($opts->{exports})|| []};if (%$opts){Exporter::Tiny::_croak('Unsupported Sub::Exporter-style options: %s',join(q[, ],sort keys %$opts),)}}ref($_)&& Exporter::Tiny::_croak('Expected sub name, got ref %s',$_)for @_;no strict qw(refs);push @{"$caller\::ISA"},'Exporter::Tiny';push @{"$caller\::EXPORT_OK"},@_}1;
53 EXPORTER_SHINY
54
55 $fatpacked{"Exporter/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXPORTER_TINY';
56 package Exporter::Tiny;use 5.006001;use strict;use warnings;no warnings qw(void once uninitialized numeric redefine);our$AUTHORITY='cpan:TOBYINK';our$VERSION='1.000000';our@EXPORT_OK=qw<mkopt mkopt_hash _croak _carp>;sub _croak ($;@) {require Carp;my$fmt=shift;@_=sprintf($fmt,@_);goto \&Carp::croak}sub _carp ($;@) {require Carp;my$fmt=shift;@_=sprintf($fmt,@_);goto \&Carp::carp}my$_process_optlist=sub {my$class=shift;my ($global_opts,$opts,$want,$not_want)=@_;while (@$opts){my$opt=shift @{$opts};my ($name,$value)=@$opt;($name =~ m{\A\!(/.+/[msixpodual]+)\z})? do {my@not=$class->_exporter_expand_regexp($1,$value,$global_opts);++$not_want->{$_->[0]}for@not}: ($name =~ m{\A\!(.+)\z})? (++$not_want->{$1}): ($name =~ m{\A[:-](.+)\z})? push(@$opts,$class->_exporter_expand_tag($1,$value,$global_opts)): ($name =~ m{\A/.+/[msixpodual]+\z})? push(@$opts,$class->_exporter_expand_regexp($name,$value,$global_opts)): push(@$want,$opt)}};sub import {my$class=shift;my$global_opts=+{@_ && ref($_[0])eq q(HASH) ? %{+shift}: ()};$global_opts->{into}=caller unless exists$global_opts->{into};my@want;my%not_want;$global_opts->{not}=\%not_want;my@args=do {no strict qw(refs);@_ ? @_ : @{"$class\::EXPORT"}};my$opts=mkopt(\@args);$class->$_process_optlist($global_opts,$opts,\@want,\%not_want);my$permitted=$class->_exporter_permitted_regexp($global_opts);$class->_exporter_validate_opts($global_opts);for my$wanted (@want){next if$not_want{$wanted->[0]};my%symbols=$class->_exporter_expand_sub(@$wanted,$global_opts,$permitted);$class->_exporter_install_sub($_,$wanted->[1],$global_opts,$symbols{$_})for keys%symbols}}sub unimport {my$class=shift;my$global_opts=+{@_ && ref($_[0])eq q(HASH) ? %{+shift}: ()};$global_opts->{into}=caller unless exists$global_opts->{into};$global_opts->{is_unimport}=1;my@want;my%not_want;$global_opts->{not}=\%not_want;my@args=do {our%TRACKED;@_ ? @_ : keys(%{$TRACKED{$class}{$global_opts->{into}}})};my$opts=mkopt(\@args);$class->$_process_optlist($global_opts,$opts,\@want,\%not_want);my$permitted=$class->_exporter_permitted_regexp($global_opts);$class->_exporter_validate_unimport_opts($global_opts);my$expando=$class->can('_exporter_expand_sub');$expando=undef if$expando==\&_exporter_expand_sub;for my$wanted (@want){next if$not_want{$wanted->[0]};if ($wanted->[1]){_carp("Passing options to unimport '%s' makes no sense",$wanted->[0])unless (ref($wanted->[1])eq 'HASH' and not keys %{$wanted->[1]})}my%symbols=defined($expando)? $class->$expando(@$wanted,$global_opts,$permitted): ($wanted->[0]=>sub {"dummy"});$class->_exporter_uninstall_sub($_,$wanted->[1],$global_opts)for keys%symbols}}sub _exporter_validate_opts {1}sub _exporter_validate_unimport_opts {1}sub _exporter_merge_opts {my$class=shift;my ($tag_opts,$global_opts,@stuff)=@_;$tag_opts={}unless ref($tag_opts)eq q(HASH);_croak('Cannot provide an -as option for tags')if exists$tag_opts->{-as}&& ref$tag_opts->{-as}ne 'CODE';my$optlist=mkopt(\@stuff);for my$export (@$optlist){next if defined($export->[1])&& ref($export->[1])ne q(HASH);my%sub_opts=(%{$export->[1]or {}},%$tag_opts);$sub_opts{-prefix}=sprintf('%s%s',$tag_opts->{-prefix},$export->[1]{-prefix})if exists($export->[1]{-prefix})&& exists($tag_opts->{-prefix});$sub_opts{-suffix}=sprintf('%s%s',$export->[1]{-suffix},$tag_opts->{-suffix})if exists($export->[1]{-suffix})&& exists($tag_opts->{-suffix});$export->[1]=\%sub_opts}return @$optlist}sub _exporter_expand_tag {no strict qw(refs);my$class=shift;my ($name,$value,$globals)=@_;my$tags=\%{"$class\::EXPORT_TAGS"};return$class->_exporter_merge_opts($value,$globals,$tags->{$name}->($class,@_))if ref($tags->{$name})eq q(CODE);return$class->_exporter_merge_opts($value,$globals,@{$tags->{$name}})if exists$tags->{$name};return$class->_exporter_merge_opts($value,$globals,@{"$class\::EXPORT"},@{"$class\::EXPORT_OK"})if$name eq 'all';return$class->_exporter_merge_opts($value,$globals,@{"$class\::EXPORT"})if$name eq 'default';$globals->{$name}=$value || 1;return}sub _exporter_expand_regexp {no strict qw(refs);our%TRACKED;my$class=shift;my ($name,$value,$globals)=@_;my$compiled=eval("qr$name");my@possible=$globals->{is_unimport}? keys(%{$TRACKED{$class}{$globals->{into}}}): @{"$class\::EXPORT_OK"};$class->_exporter_merge_opts($value,$globals,grep /$compiled/,@possible)}sub _exporter_permitted_regexp {no strict qw(refs);my$class=shift;my$re=join "|",map quotemeta,sort {length($b)<=> length($a)or $a cmp $b}@{"$class\::EXPORT"},@{"$class\::EXPORT_OK"};qr{^(?:$re)$}ms}sub _exporter_expand_sub {my$class=shift;my ($name,$value,$globals,$permitted)=@_;$permitted ||= $class->_exporter_permitted_regexp($globals);no strict qw(refs);if ($name =~ $permitted){my$generator=$class->can("_generate_$name");return$name=>$class->$generator($name,$value,$globals)if$generator;my$sub=$class->can($name);return$name=>$sub if$sub}$class->_exporter_fail(@_)}sub _exporter_fail {my$class=shift;my ($name,$value,$globals)=@_;return if$globals->{is_unimport};_croak("Could not find sub '%s' exported by %s",$name,$class)}sub _exporter_install_sub {my$class=shift;my ($name,$value,$globals,$sym)=@_;my$into=$globals->{into};my$installer=$globals->{installer}|| $globals->{exporter};$name=ref$globals->{as}? $globals->{as}->($name): ref$value->{-as}? $value->{-as}->($name): exists$value->{-as}? $value->{-as}: $name;return unless defined$name;unless (ref($name)){my ($prefix)=grep defined,$value->{-prefix},$globals->{prefix},q();my ($suffix)=grep defined,$value->{-suffix},$globals->{suffix},q();$name="$prefix$name$suffix"}return ($$name=$sym)if ref($name)eq q(SCALAR);return ($into->{$name}=$sym)if ref($into)eq q(HASH);no strict qw(refs);if (exists &{"$into\::$name"}and \&{"$into\::$name"}!=$sym){my ($level)=grep defined,$value->{-replace},$globals->{replace},q(0);my$action={carp=>\&_carp,0=>\&_carp,''=>\&_carp,warn=>\&_carp,nonfatal=>\&_carp,croak=>\&_croak,fatal=>\&_croak,die=>\&_croak,}->{$level}|| sub {};$action->($action==\&_croak ? "Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s" : "Overwriting existing sub '%s::%s' with sub '%s' exported by %s",$into,$name,$_[0],$class,)}our%TRACKED;$TRACKED{$class}{$into}{$name}=$sym;no warnings qw(prototype);$installer ? $installer->($globals,[$name,$sym]): (*{"$into\::$name"}=$sym)}sub _exporter_uninstall_sub {our%TRACKED;my$class=shift;my ($name,$value,$globals,$sym)=@_;my$into=$globals->{into};ref$into and return;no strict qw(refs);my$our_coderef=$TRACKED{$class}{$into}{$name};my$cur_coderef=exists(&{"$into\::$name"})? \&{"$into\::$name"}: -1;return unless$our_coderef==$cur_coderef;my$stash=\%{"$into\::"};my$old=delete$stash->{$name};my$full_name=join('::',$into,$name);for my$type (qw(SCALAR HASH ARRAY IO)){next unless defined(*{$old}{$type});*$full_name=*{$old}{$type}}delete$TRACKED{$class}{$into}{$name}}sub mkopt {my$in=shift or return [];my@out;$in=[map(($_=>ref($in->{$_})? $in->{$_}: ()),sort keys %$in)]if ref($in)eq q(HASH);for (my$i=0;$i < @$in;$i++){my$k=$in->[$i];my$v;($i==$#$in)? ($v=undef): !defined($in->[$i+1])? (++$i,($v=undef)): !ref($in->[$i+1])? ($v=undef): ($v=$in->[++$i]);push@out,[$k=>$v ]}\@out}sub mkopt_hash {my$in=shift or return;my%out=map +($_->[0]=>$_->[1]),@{mkopt($in)};\%out}1;
57 EXPORTER_TINY
58
59 $fatpacked{"ExtUtils/Config.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_CONFIG';
60 package ExtUtils::Config;$ExtUtils::Config::VERSION='0.008';use strict;use warnings;use Config;use Data::Dumper ();sub new {my ($pack,$args)=@_;return bless {values=>($args ? {%$args }: {}),},$pack}sub get {my ($self,$key)=@_;return exists$self->{values}{$key}? $self->{values}{$key}: $Config{$key}}sub exists {my ($self,$key)=@_;return exists$self->{values}{$key}|| exists$Config{$key}}sub values_set {my$self=shift;return {%{$self->{values}}}}sub all_config {my$self=shift;return {%Config,%{$self->{values}}}}sub serialize {my$self=shift;return$self->{serialized}||= Data::Dumper->new([$self->values_set])->Terse(1)->Sortkeys(1)->Dump}1;
61 EXTUTILS_CONFIG
62
63 $fatpacked{"ExtUtils/Helpers.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_HELPERS';
64 package ExtUtils::Helpers;$ExtUtils::Helpers::VERSION='0.026';use strict;use warnings FATAL=>'all';use Exporter 5.57 'import';use Config;use File::Basename qw/basename/;use File::Spec::Functions qw/splitpath canonpath abs2rel splitdir/;use Text::ParseWords 3.24 ();our@EXPORT_OK=qw/make_executable split_like_shell man1_pagename man3_pagename detildefy/;BEGIN {my%impl_for=(MSWin32=>'Windows',VMS=>'VMS');my$package='ExtUtils::Helpers::' .($impl_for{$^O}|| 'Unix');my$impl=$impl_for{$^O}|| 'Unix';require "ExtUtils/Helpers/$impl.pm";"ExtUtils::Helpers::$impl"->import()}sub split_like_shell {my ($string)=@_;return if not defined$string;$string =~ s/^\s+|\s+$//g;return if not length$string;return Text::ParseWords::shellwords($string)}sub man1_pagename {my$filename=shift;return basename($filename).".$Config{man1ext}"}my%separator=(MSWin32=>'.',VMS=>'__',os2=>'.',cygwin=>'.',);my$separator=$separator{$^O}|| '::';sub man3_pagename {my ($filename,$base)=@_;$base ||= 'lib';my ($vols,$dirs,$file)=splitpath(canonpath(abs2rel($filename,$base)));$file=basename($file,qw/.pm .pod/);my@dirs=grep {length}splitdir($dirs);return join$separator,@dirs,"$file.$Config{man3ext}"}1;
65 EXTUTILS_HELPERS
66
67 $fatpacked{"ExtUtils/Helpers/Unix.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_HELPERS_UNIX';
68 package ExtUtils::Helpers::Unix;$ExtUtils::Helpers::Unix::VERSION='0.026';use strict;use warnings FATAL=>'all';use Exporter 5.57 'import';our@EXPORT=qw/make_executable detildefy/;use Carp qw/croak/;use Config;my$layer=$] >= 5.008001 ? ":raw" : "";sub make_executable {my$filename=shift;my$current_mode=(stat$filename)[2]+ 0;if (-T $filename){open my$fh,"<$layer",$filename;my@lines=<$fh>;if (@lines and $lines[0]=~ s{ \A \#! \s* (?:/\S+/)? perl \b (.*) \z }{$Config{startperl}$1}xms){open my$out,">$layer","$filename.new" or croak "Couldn't open $filename.new: $!";print$out @lines;close$out;rename$filename,"$filename.bak" or croak "Couldn't rename $filename to $filename.bak";rename "$filename.new",$filename or croak "Couldn't rename $filename.new to $filename";unlink "$filename.bak"}}chmod$current_mode | oct(111),$filename;return}sub detildefy {my$value=shift;for ($value){s{ ^ ~ (?= /|$)} [ $ENV{HOME} || (getpwuid $>)[7] ]ex or s{ ^ ~ ([^/]+) (?= /|$) } { (getpwnam $1)[7] || "~$1" }ex}return$value}1;
69 EXTUTILS_HELPERS_UNIX
70
71 $fatpacked{"ExtUtils/Helpers/VMS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_HELPERS_VMS';
72 package ExtUtils::Helpers::VMS;$ExtUtils::Helpers::VMS::VERSION='0.026';use strict;use warnings FATAL=>'all';use Exporter 5.57 'import';our@EXPORT=qw/make_executable detildefy/;use File::Copy qw/copy/;sub make_executable {my$filename=shift;my$batchname="$filename.com";copy($filename,$batchname);ExtUtils::Helpers::Unix::make_executable($batchname);return}sub detildefy {my$arg=shift;return$arg if ($arg =~ /^~~/);return$arg if ($arg =~ /^~ /);if ($arg =~ /^~/){my$spec=$arg;$spec =~ s/^~//;$spec =~ s#^/##;my$home=VMS::Filespec::unixify($ENV{HOME});$home .= '/' unless$home =~ m#/$#;if ($spec eq ''){$home =~ s#/$##;return$home}my ($hvol,$hdir,$hfile)=File::Spec::Unix->splitpath($home);if ($hdir eq ''){$hdir=$hfile}my ($vol,$dir,$file)=File::Spec::Unix->splitpath($spec);my@hdirs=File::Spec::Unix->splitdir($hdir);my@dirs=File::Spec::Unix->splitdir($dir);unless ($arg =~ m#^~/#){shift@dirs}my$newdirs=File::Spec::Unix->catdir(@hdirs,@dirs);$arg=File::Spec::Unix->catpath($hvol,$newdirs,$file)}return$arg}
73 EXTUTILS_HELPERS_VMS
74
75 $fatpacked{"ExtUtils/Helpers/Windows.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_HELPERS_WINDOWS';
76 package ExtUtils::Helpers::Windows;$ExtUtils::Helpers::Windows::VERSION='0.026';use strict;use warnings FATAL=>'all';use Exporter 5.57 'import';our@EXPORT=qw/make_executable detildefy/;use Config;use Carp qw/carp croak/;use ExtUtils::PL2Bat 'pl2bat';sub make_executable {my$script=shift;if (-T $script && $script !~ / \. (?:bat|cmd) $ /x){pl2bat(in=>$script,update=>1)}return}sub detildefy {my$value=shift;$value =~ s{ ^ ~ (?= [/\\] | $ ) }[$ENV{USERPROFILE}]x if$ENV{USERPROFILE};return$value}1;
77 EXTUTILS_HELPERS_WINDOWS
78
79 $fatpacked{"ExtUtils/InstallPaths.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'EXTUTILS_INSTALLPATHS';
80 package ExtUtils::InstallPaths;$ExtUtils::InstallPaths::VERSION='0.011';use 5.006;use strict;use warnings;use File::Spec ();use Carp ();use ExtUtils::Config 0.002;my%complex_accessors=map {$_=>1}qw/prefix_relpaths install_sets/;my%hash_accessors=map {$_=>1}qw/install_path install_base_relpaths original_prefix/;my%defaults=(installdirs=>'site',install_base=>undef,prefix=>undef,verbose=>0,blib=>'blib',create_packlist=>1,dist_name=>undef,module_name=>undef,destdir=>undef,install_path=>sub {{}},install_sets=>\&_default_install_sets,original_prefix=>\&_default_original_prefix,install_base_relpaths=>\&_default_base_relpaths,prefix_relpaths=>\&_default_prefix_relpaths,);sub _merge_shallow {my ($name,$filter)=@_;return sub {my ($override,$config)=@_;my$defaults=$defaults{$name}->($config);$filter->($_)for grep$filter,values %$override;return {%$defaults,%$override }}}sub _merge_deep {my ($name,$filter)=@_;return sub {my ($override,$config)=@_;my$defaults=$defaults{$name}->($config);my$pair_for=sub {my$key=shift;my%override=%{$override->{$key}|| {}};$filter && $filter->($_)for values%override;return$key=>{%{$defaults->{$key}},%override }};return {map {$pair_for->($_)}keys %$defaults }}}my%allowed_installdir=map {$_=>1}qw/core site vendor/;my$must_be_relative=sub {Carp::croak('Value must be a relative path')if File::Spec->file_name_is_absolute($_[0])};my%deep_filter=map {$_=>$must_be_relative}qw/install_base_relpaths prefix_relpaths/;my%filter=(installdirs=>sub {my$value=shift;$value='core',Carp::carp('Perhaps you meant installdirs to be "core" rather than "perl"?')if$value eq 'perl';Carp::croak('installdirs must be one of "core", "site", or "vendor"')if not $allowed_installdir{$value};return$value},(map {$_=>_merge_shallow($_,$deep_filter{$_})}qw/original_prefix install_base_relpaths/),(map {$_=>_merge_deep($_,$deep_filter{$_})}qw/install_sets prefix_relpaths/),);sub new {my ($class,%args)=@_;my$config=$args{config}|| ExtUtils::Config->new;my%self=(config=>$config,map {$_=>exists$args{$_}? $filter{$_}? $filter{$_}->($args{$_},$config): $args{$_}: ref$defaults{$_}? $defaults{$_}->($config): $defaults{$_}}keys%defaults,);$self{module_name}||= do {my$module_name=$self{dist_name};$module_name =~ s/-/::/g;$module_name}if defined$self{dist_name};return bless \%self,$class}for my$attribute (keys%defaults){no strict qw/refs/;*{$attribute}=$hash_accessors{$attribute}? sub {my ($self,$key)=@_;Carp::confess("$attribute needs key")if not defined$key;return$self->{$attribute}{$key}}: $complex_accessors{$attribute}? sub {my ($self,$installdirs,$key)=@_;Carp::confess("$attribute needs installdir")if not defined$installdirs;Carp::confess("$attribute needs key")if not defined$key;return$self->{$attribute}{$installdirs}{$key}}: sub {my$self=shift;return$self->{$attribute}}}my$script=$] > 5.008000 ? 'script' : 'bin';my@install_sets_keys=qw/lib arch bin script bindoc libdoc binhtml libhtml/;my@install_sets_tail=('bin',$script,qw/man1dir man3dir html1dir html3dir/);my%install_sets_values=(core=>[qw/privlib archlib/,@install_sets_tail ],site=>[map {"site$_"}qw/lib arch/,@install_sets_tail ],vendor=>[map {"vendor$_"}qw/lib arch/,@install_sets_tail ],);sub _default_install_sets {my$c=shift;my%ret;for my$installdir (qw/core site vendor/){@{$ret{$installdir}}{@install_sets_keys}=map {$c->get("install$_")}@{$install_sets_values{$installdir}}}return \%ret}sub _default_base_relpaths {my$config=shift;return {lib=>['lib','perl5'],arch=>['lib','perl5',$config->get('archname')],bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],}}my%common_prefix_relpaths=(bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],);sub _default_prefix_relpaths {my$c=shift;my@libstyle=$c->get('installstyle')? File::Spec->splitdir($c->get('installstyle')): qw(lib perl5);my$arch=$c->get('archname');my$version=$c->get('version');return {core=>{lib=>[@libstyle],arch=>[@libstyle,$version,$arch],%common_prefix_relpaths,},vendor=>{lib=>[@libstyle],arch=>[@libstyle,$version,$arch],%common_prefix_relpaths,},site=>{lib=>[@libstyle,'site_perl'],arch=>[@libstyle,'site_perl',$version,$arch],%common_prefix_relpaths,},}}sub _default_original_prefix {my$c=shift;my%ret=(core=>$c->get('installprefixexp'),site=>$c->get('siteprefixexp'),vendor=>$c->get('usevendorprefix')? $c->get('vendorprefixexp'): '',);return \%ret}sub _log_verbose {my$self=shift;print @_ if$self->verbose;return}sub is_default_installable {my$self=shift;my$type=shift;my$installable=$self->install_destination($type)&& ($self->install_path($type)|| $self->install_sets($self->installdirs,$type));return$installable ? 1 : 0}sub _prefixify_default {my$self=shift;my$type=shift;my$rprefix=shift;my$default=$self->prefix_relpaths($self->installdirs,$type);if(!$default){$self->_log_verbose(" no default install location for type '$type', using prefix '$rprefix'.\n");return$rprefix}else {return File::Spec->catdir(@{$default})}}sub _prefixify_novms {my($self,$path,$sprefix,$type)=@_;my$rprefix=$self->prefix;$rprefix .= '/' if$sprefix =~ m{/$};$self->_log_verbose(" prefixify $path from $sprefix to $rprefix\n")if defined$path && length$path;if (not defined$path or length$path==0){$self->_log_verbose(" no path to prefixify, falling back to default.\n");return$self->_prefixify_default($type,$rprefix)}elsif(!File::Spec->file_name_is_absolute($path)){$self->_log_verbose(" path is relative, not prefixifying.\n")}elsif($path !~ s{^\Q$sprefix\E\b}{}s){$self->_log_verbose(" cannot prefixify, falling back to default.\n");return$self->_prefixify_default($type,$rprefix)}$self->_log_verbose(" now $path in $rprefix\n");return$path}sub _catprefix_vms {my ($self,$rprefix,$default)=@_;my ($rvol,$rdirs)=File::Spec->splitpath($rprefix);if ($rvol){return File::Spec->catpath($rvol,File::Spec->catdir($rdirs,$default),'')}else {return File::Spec->catdir($rdirs,$default)}}sub _prefixify_vms {my($self,$path,$sprefix,$type)=@_;my$rprefix=$self->prefix;return '' unless defined$path;$self->_log_verbose(" prefixify $path from $sprefix to $rprefix\n");require VMS::Filespec;$rprefix=VMS::Filespec::vmspath($rprefix)if$rprefix;$sprefix=VMS::Filespec::vmspath($sprefix)if$sprefix;$self->_log_verbose(" rprefix translated to $rprefix\n sprefix translated to $sprefix\n");if (length($path)==0){$self->_log_verbose(" no path to prefixify.\n")}elsif (!File::Spec->file_name_is_absolute($path)){$self->_log_verbose(" path is relative, not prefixifying.\n")}elsif ($sprefix eq $rprefix){$self->_log_verbose(" no new prefix.\n")}else {my ($path_vol,$path_dirs)=File::Spec->splitpath($path);my$vms_prefix=$self->config->get('vms_prefix');if ($path_vol eq $vms_prefix.':'){$self->_log_verbose(" $vms_prefix: seen\n");$path_dirs =~ s{^\[}{\[.} unless$path_dirs =~ m{^\[\.};$path=$self->_catprefix_vms($rprefix,$path_dirs)}else {$self->_log_verbose(" cannot prefixify.\n");return File::Spec->catdir($self->prefix_relpaths($self->installdirs,$type))}}$self->_log_verbose(" now $path\n");return$path}BEGIN {*_prefixify=$^O eq 'VMS' ? \&_prefixify_vms : \&_prefixify_novms}sub prefix_relative {my ($self,$installdirs,$type)=@_;my$relpath=$self->install_sets($installdirs,$type);return$self->_prefixify($relpath,$self->original_prefix($installdirs),$type)}sub install_destination {my ($self,$type)=@_;return$self->install_path($type)if$self->install_path($type);if ($self->install_base){my$relpath=$self->install_base_relpaths($type);return$relpath ? File::Spec->catdir($self->install_base,@{$relpath}): undef}if ($self->prefix){my$relpath=$self->prefix_relative($self->installdirs,$type);return$relpath ? File::Spec->catdir($self->prefix,$relpath): undef}return$self->install_sets($self->installdirs,$type)}sub install_types {my$self=shift;my%types=(%{$self->{install_path}},$self->install_base ? %{$self->{install_base_relpaths}}: $self->prefix ? %{$self->{prefix_relpaths}{$self->installdirs }}: %{$self->{install_sets}{$self->installdirs }});return sort keys%types}sub install_map {my ($self,$blib)=@_;$blib ||= $self->blib;my (%map,@skipping);for my$type ($self->install_types){my$localdir=File::Spec->catdir($blib,$type);next unless -e $localdir;if (my$dest=$self->install_destination($type)){$map{$localdir}=$dest}else {push@skipping,$type}}warn "WARNING: Can't figure out install path for types: @skipping\nFiles will not be installed.\n" if@skipping;if ($self->create_packlist and my$module_name=$self->module_name){my$archdir=$self->install_destination('arch');my@ext=split /::/,$module_name;$map{write}=File::Spec->catfile($archdir,'auto',@ext,'.packlist')}if (length(my$destdir=$self->destdir || '')){for (keys%map){my ($volume,$path,$file)=File::Spec->splitpath($map{$_},0);my@dirs=File::Spec->splitdir($path);$path=File::Spec->catdir($destdir,@dirs);if ($file ne ''){$map{$_}=File::Spec->catfile($path,$file)}else {$map{$_}=$path}}}$map{read}='';return \%map}1;
81 EXTUTILS_INSTALLPATHS
82
83 $fatpacked{"File/Slurp.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'FILE_SLURP';
84 package File::Slurp;use 5.6.2 ;use strict;use warnings ;use Carp ;use Exporter ;use Fcntl qw(:DEFAULT) ;use POSIX qw(:fcntl_h) ;use Errno ;use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION) ;@ISA=qw(Exporter) ;$VERSION='9999.19';my@std_export=qw(read_file write_file overwrite_file append_file read_dir) ;my@edit_export=qw(edit_file edit_file_lines) ;my@ok_export=qw() ;@EXPORT_OK=(@edit_export,qw(slurp prepend_file),);%EXPORT_TAGS=('all'=>[@std_export,@edit_export,@EXPORT_OK ],'edit'=>[@edit_export ],'std'=>[@std_export ],);@EXPORT=@std_export ;my$max_fast_slurp_size=1024 * 100 ;my$is_win32=$^O =~ /win32/i ;BEGIN {unless(defined&SEEK_SET){*SEEK_SET=sub {0};*SEEK_CUR=sub {1};*SEEK_END=sub {2}}unless(defined&O_BINARY){*O_BINARY=sub {0};*O_RDONLY=sub {0};*O_WRONLY=sub {1}}unless (defined&O_APPEND){if ($^O =~ /olaris/){*O_APPEND=sub {8};*O_CREAT=sub {256};*O_EXCL=sub {1024}}elsif ($^O =~ /inux/){*O_APPEND=sub {1024};*O_CREAT=sub {64};*O_EXCL=sub {128}}elsif ($^O =~ /BSD/i){*O_APPEND=sub {8};*O_CREAT=sub {512};*O_EXCL=sub {2048}}}}*slurp=\&read_file ;sub read_file {my$file_name=shift ;my$opts=(ref $_[0]eq 'HASH')? shift : {@_};if (!ref$file_name && -e $file_name && -s _ > 0 && -s _ < $max_fast_slurp_size &&!%{$opts}&&!wantarray){my$fh ;unless(sysopen($fh,$file_name,O_RDONLY)){@_=($opts,"read_file '$file_name' - sysopen: $!");goto&_error }my$read_cnt=sysread($fh,my$buf,-s _);unless (defined$read_cnt){@_=($opts,"read_file '$file_name' - small sysread: $!");goto&_error }$buf =~ s/\015\012/\n/g if$is_win32 ;return$buf }my$buf ;my$buf_ref=$opts->{'buf_ref'}|| \$buf ;${$buf_ref}='' ;my($read_fh,$size_left,$blk_size);if (ref$file_name){my$ref_result=_check_ref($file_name);if (ref$ref_result){@_=($opts,$ref_result);goto&_error }if ($ref_result){$file_name=$ref_result }else {$read_fh=$file_name ;$blk_size=$opts->{'blk_size'}|| 1024 * 1024 ;$size_left=$blk_size }}unless ($read_fh){my$mode=O_RDONLY ;$read_fh=local(*FH);unless (sysopen($read_fh,$file_name,$mode)){@_=($opts,"read_file '$file_name' - sysopen: $!");goto&_error }if (my$binmode=$opts->{'binmode'}){binmode($read_fh,$binmode)}$size_left=-s $read_fh ;unless($size_left){$blk_size=$opts->{'blk_size'}|| 1024 * 1024 ;$size_left=$blk_size }}while(1){my$read_cnt=sysread($read_fh,${$buf_ref},$size_left,length ${$buf_ref});next if $!{EINTR};unless (defined$read_cnt){@_=($opts,"read_file '$file_name' - loop sysread: $!");goto&_error }last if$read_cnt==0 ;next if$blk_size ;$size_left -= $read_cnt ;last if$size_left <= 0 }${$buf_ref}=~ s/\015\012/\n/g if$is_win32 &&!$opts->{'binmode'};my$sep=$/ ;$sep='\n\n+' if defined$sep && $sep eq '' ;if(wantarray || $opts->{'array_ref'}){use re 'taint' ;my@lines=length(${$buf_ref})? ${$buf_ref}=~ /(.*?$sep|.+)/sg : ();chomp@lines if$opts->{'chomp'};return \@lines if$opts->{'array_ref'};return@lines }return$buf_ref if$opts->{'scalar_ref'};return ${$buf_ref}if defined wantarray ;return }sub _check_ref {my($handle)=@_ ;if (eval {$handle->isa('GLOB')|| $handle->isa('IO')}){my$err=_seek_data_handle($handle);return \$err if$err ;return }eval {require overload};return \"Bad handle '$handle' is not a GLOB or IO object or overloaded" if $@ ||!overload::Overloaded($handle);return "$handle" }sub _seek_data_handle {my($handle)=@_ ;eval{require B};if ($@){return <<ERR }if (B::svref_2object($handle)->IO->IoFLAGS & 16){unless(sysseek($handle,tell($handle),SEEK_SET)){return "read_file '$handle' - sysseek: $!" }}return }sub write_file {my$file_name=shift ;my$opts=(ref $_[0]eq 'HASH')? shift : {};my($buf_ref,$write_fh,$no_truncate,$orig_file_name,$data_is_ref);if (ref$opts->{'buf_ref'}eq 'SCALAR'){$buf_ref=$opts->{'buf_ref'};$data_is_ref=1 }elsif (ref $_[0]eq 'SCALAR'){$buf_ref=shift ;$data_is_ref=1 }elsif (ref $_[0]eq 'ARRAY'){${$buf_ref}=join '',@{$_[0]}}else {${$buf_ref}=join '',@_ }if (ref$file_name){my$ref_result=_check_ref($file_name);if (ref$ref_result){@_=($opts,$ref_result);goto&_error }if ($ref_result){$file_name=$ref_result }else {$write_fh=$file_name ;$no_truncate=1 }}unless($write_fh){if ($opts->{'atomic'}){$orig_file_name=$file_name ;$file_name .= ".$$" }my$mode=O_WRONLY | O_CREAT ;$mode |= O_APPEND if$opts->{'append'};$mode |= O_EXCL if$opts->{'no_clobber'};my$perms=$opts->{perms};$perms=0666 unless defined$perms ;$write_fh=local(*FH);unless (sysopen($write_fh,$file_name,$mode,$perms)){@_=($opts,"write_file '$file_name' - sysopen: $!");goto&_error }}if (my$binmode=$opts->{'binmode'}){binmode($write_fh,$binmode)}sysseek($write_fh,0,SEEK_END)if$opts->{'append'};if ($is_win32 &&!$opts->{'binmode'}){$buf_ref=\do{my$copy=${$buf_ref}}if$data_is_ref ;${$buf_ref}=~ s/\n/\015\012/g }my$size_left=length(${$buf_ref});my$offset=0 ;do {my$write_cnt=syswrite($write_fh,${$buf_ref},$size_left,$offset);next if $!{EINTR};unless (defined$write_cnt){@_=($opts,"write_file '$file_name' - syswrite: $!");goto&_error }$size_left -= $write_cnt ;$offset += $write_cnt }while($size_left > 0);truncate($write_fh,sysseek($write_fh,0,SEEK_CUR))unless$no_truncate ;close($write_fh);if ($opts->{'atomic'}&&!rename($file_name,$orig_file_name)){@_=($opts,"write_file '$file_name' - rename: $!");goto&_error }return 1 }*overwrite_file=\&write_file ;sub append_file {my$opts=$_[1];if (ref$opts eq 'HASH'){$opts->{append}=1 }else {splice(@_,1,0,{append=>1 })}goto&write_file}sub prepend_file {my$file_name=shift ;my$opts=(ref $_[0]eq 'HASH')? shift : {};my@bad_opts=grep $_ ne 'err_mode' && $_ ne 'binmode',keys %{$opts};delete @{$opts}{@bad_opts};my$prepend_data=shift ;$prepend_data='' unless defined$prepend_data ;$prepend_data=${$prepend_data}if ref$prepend_data eq 'SCALAR' ;my$err_mode=delete$opts->{err_mode};$opts->{err_mode }='croak' ;$opts->{scalar_ref }=1 ;my$existing_data=eval {read_file($file_name,$opts)};if ($@){@_=({err_mode=>$err_mode },"prepend_file '$file_name' - read_file: $!");goto&_error }$opts->{atomic}=1 ;my$write_result=eval {write_file($file_name,$opts,$prepend_data,$$existing_data)};if ($@){@_=({err_mode=>$err_mode },"prepend_file '$file_name' - write_file: $!");goto&_error }return$write_result }sub edit_file(&$;$) {my($edit_code,$file_name,$opts)=@_ ;$opts={}unless ref$opts eq 'HASH' ;my@bad_opts=grep $_ ne 'err_mode' && $_ ne 'binmode',keys %{$opts};delete @{$opts}{@bad_opts};my$err_mode=delete$opts->{err_mode};$opts->{err_mode }='croak' ;$opts->{scalar_ref }=1 ;my$existing_data=eval {read_file($file_name,$opts)};if ($@){@_=({err_mode=>$err_mode },"edit_file '$file_name' - read_file: $!");goto&_error }my($edited_data)=map {$edit_code->();$_}$$existing_data ;$opts->{atomic}=1 ;my$write_result=eval {write_file($file_name,$opts,$edited_data)};if ($@){@_=({err_mode=>$err_mode },"edit_file '$file_name' - write_file: $!");goto&_error }return$write_result }sub edit_file_lines(&$;$) {my($edit_code,$file_name,$opts)=@_ ;$opts={}unless ref$opts eq 'HASH' ;my@bad_opts=grep $_ ne 'err_mode' && $_ ne 'binmode',keys %{$opts};delete @{$opts}{@bad_opts};my$err_mode=delete$opts->{err_mode};$opts->{err_mode }='croak' ;$opts->{array_ref }=1 ;my$existing_data=eval {read_file($file_name,$opts)};if ($@){@_=({err_mode=>$err_mode },"edit_file_lines '$file_name' - read_file: $!");goto&_error }my@edited_data=map {$edit_code->();$_}@$existing_data ;$opts->{atomic}=1 ;my$write_result=eval {write_file($file_name,$opts,@edited_data)};if ($@){@_=({err_mode=>$err_mode },"edit_file_lines '$file_name' - write_file: $!");goto&_error }return$write_result }sub read_dir {my$dir=shift ;my$opts=(ref $_[0]eq 'HASH')? shift : {@_};local(*DIRH);unless (opendir(DIRH,$dir)){@_=($opts,"read_dir '$dir' - opendir: $!");goto&_error }my@dir_entries=readdir(DIRH);@dir_entries=grep($_ ne "." && $_ ne "..",@dir_entries)unless$opts->{'keep_dot_dot'};if ($opts->{'prefix'}){substr($_,0,0,"$dir/")for@dir_entries }return@dir_entries if wantarray ;return \@dir_entries }my%err_func=('carp'=>\&carp,'croak'=>\&croak,);sub _error {my($opts,$err_msg)=@_ ;my$func=$err_func{$opts->{'err_mode'}|| 'croak' };return unless$func ;$func->($err_msg)if$func ;return undef }1;
85 Can't find B.pm with this Perl: $!.
86 That module is needed to properly slurp the DATA handle.
87 ERR
88 FILE_SLURP
89
90 $fatpacked{"File/chdir.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'FILE_CHDIR';
91 package File::chdir;use 5.004;use strict;use vars qw($VERSION @ISA @EXPORT $CWD @CWD);our$VERSION='0.1010';require Exporter;@ISA=qw(Exporter);@EXPORT=qw(*CWD);use Carp;use Cwd 3.16;use File::Spec::Functions 3.27 qw/canonpath splitpath catpath splitdir catdir/;tie$CWD,'File::chdir::SCALAR' or die "Can't tie \$CWD";tie@CWD,'File::chdir::ARRAY' or die "Can't tie \@CWD";sub _abs_path {my($cwd)=Cwd::getcwd =~ /(.*)/s;return canonpath($cwd)}sub _split_cwd {my ($vol,$dir)=splitpath(_abs_path,1);my@dirs=splitdir($dir);shift@dirs;return ($vol,@dirs)}sub _catpath {my ($vol,@dirs)=@_;return catpath($vol,catdir(q{},@dirs),q{})}sub _chdir {my ($new_dir)=$_[0]=~ /(.*)/s;local$Carp::CarpLevel=$Carp::CarpLevel + 1;if (!CORE::chdir($new_dir)){croak "Failed to change directory to '$new_dir': $!"};return 1}{package File::chdir::SCALAR;use Carp;BEGIN {*_abs_path=\&File::chdir::_abs_path;*_chdir=\&File::chdir::_chdir;*_split_cwd=\&File::chdir::_split_cwd;*_catpath=\&File::chdir::_catpath}sub TIESCALAR {bless [],$_[0]}sub FETCH {return _abs_path}sub STORE {return unless defined $_[1];_chdir($_[1])}}{package File::chdir::ARRAY;use Carp;BEGIN {*_abs_path=\&File::chdir::_abs_path;*_chdir=\&File::chdir::_chdir;*_split_cwd=\&File::chdir::_split_cwd;*_catpath=\&File::chdir::_catpath}sub TIEARRAY {bless {},$_[0]}sub FETCH {my($self,$idx)=@_;my ($vol,@cwd)=_split_cwd;return$cwd[$idx]}sub STORE {my($self,$idx,$val)=@_;my ($vol,@cwd)=_split_cwd;if($self->{Cleared}){@cwd=();$self->{Cleared}=0}$cwd[$idx]=$val;my$dir=_catpath($vol,@cwd);_chdir($dir);return$cwd[$idx]}sub FETCHSIZE {my ($vol,@cwd)=_split_cwd;return scalar@cwd}sub STORESIZE {}sub PUSH {my($self)=shift;my$dir=_catpath(_split_cwd,@_);_chdir($dir);return$self->FETCHSIZE}sub POP {my($self)=shift;my ($vol,@cwd)=_split_cwd;my$popped=pop@cwd;my$dir=_catpath($vol,@cwd);_chdir($dir);return$popped}sub SHIFT {my($self)=shift;my ($vol,@cwd)=_split_cwd;my$shifted=shift@cwd;my$dir=_catpath($vol,@cwd);_chdir($dir);return$shifted}sub UNSHIFT {my($self)=shift;my ($vol,@cwd)=_split_cwd;my$dir=_catpath($vol,@_,@cwd);_chdir($dir);return$self->FETCHSIZE}sub CLEAR {my($self)=shift;$self->{Cleared}=1}sub SPLICE {my$self=shift;my$offset=shift || 0;my$len=shift || $self->FETCHSIZE - $offset;my@new_dirs=@_;my ($vol,@cwd)=_split_cwd;my@orig_dirs=splice@cwd,$offset,$len,@new_dirs;my$dir=_catpath($vol,@cwd);_chdir($dir);return@orig_dirs}sub EXTEND {}sub EXISTS {my($self,$idx)=@_;return$self->FETCHSIZE >= $idx ? 1 : 0}sub DELETE {my($self,$idx)=@_;croak "Can't delete except at the end of \@CWD" if$idx < $self->FETCHSIZE - 1;local$Carp::CarpLevel=$Carp::CarpLevel + 1;$self->POP}}1;
92 FILE_CHDIR
93
94 $fatpacked{"List/MoreUtils.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIST_MOREUTILS';
95 package List::MoreUtils;use 5.008_001;use strict;use warnings;my$have_xs;our$VERSION='0.428';BEGIN {unless (defined($have_xs)){eval {require List::MoreUtils::XS}unless$ENV{LIST_MOREUTILS_PP};die $@ if $@ && defined$ENV{LIST_MOREUTILS_PP}&& $ENV{LIST_MOREUTILS_PP}==0;$have_xs=0+defined($INC{'List/MoreUtils/XS.pm'})}use List::MoreUtils::PP qw()}use Exporter::Tiny qw();my@junctions=qw(any all none notall);my@v0_22=qw(true false firstidx lastidx insert_after insert_after_string apply indexes after after_incl before before_incl firstval lastval each_array each_arrayref pairwise natatime mesh uniq minmax part _XScompiled);my@v0_24=qw(bsearch);my@v0_33=qw(sort_by nsort_by);my@v0_400=qw(one any_u all_u none_u notall_u one_u firstres onlyidx onlyval onlyres lastres singleton bsearchidx);my@v0_420=qw(arrayify duplicates minmaxstr samples zip6 reduce_0 reduce_1 reduce_u listcmp frequency occurrences mode binsert bremove equal_range lower_bound upper_bound qsort);my@all_functions=(@junctions,@v0_22,@v0_24,@v0_33,@v0_400,@v0_420);no strict "refs";if ($have_xs){my$x;for (@all_functions){List::MoreUtils->can($_)or *$_=$x if ($x=List::MoreUtils::XS->can($_))}}List::MoreUtils->can($_)or *$_=List::MoreUtils::PP->can($_)for (@all_functions);use strict;my%alias_list=(v0_22=>{first_index=>"firstidx",last_index=>"lastidx",first_value=>"firstval",last_value=>"lastval",zip=>"mesh",},v0_33=>{distinct=>"uniq",},v0_400=>{first_result=>"firstres",only_index=>"onlyidx",only_value=>"onlyval",only_result=>"onlyres",last_result=>"lastres",bsearch_index=>"bsearchidx",},v0_420=>{bsearch_insert=>"binsert",bsearch_remove=>"bremove",zip_unflatten=>"zip6",},);our@ISA=qw(Exporter::Tiny);our@EXPORT_OK=(@all_functions,map {keys %$_}values%alias_list);our%EXPORT_TAGS=(all=>\@EXPORT_OK,'like_0.22'=>[any_u=>{-as=>'any'},all_u=>{-as=>'all'},none_u=>{-as=>'none'},notall_u=>{-as=>'notall'},@v0_22,keys %{$alias_list{v0_22}},],'like_0.24'=>[any_u=>{-as=>'any'},all_u=>{-as=>'all'},notall_u=>{-as=>'notall'},'none',@v0_22,@v0_24,keys %{$alias_list{v0_22}},],'like_0.33'=>[@junctions,@v0_22,@v0_33,keys %{$alias_list{v0_22}},keys %{$alias_list{v0_33}},],);for my$set (values%alias_list){for my$alias (keys %$set){no strict qw(refs);*$alias=__PACKAGE__->can($set->{$alias})}}1;
96 LIST_MOREUTILS
97
98 $fatpacked{"List/MoreUtils/PP.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIST_MOREUTILS_PP';
99 package List::MoreUtils::PP;use 5.008_001;use strict;use warnings;our$VERSION='0.428';sub any (&@) {my$f=shift;for (@_){return 1 if$f->()}return 0}sub all (&@) {my$f=shift;for (@_){return 0 unless$f->()}return 1}sub none (&@) {my$f=shift;for (@_){return 0 if$f->()}return 1}sub notall (&@) {my$f=shift;for (@_){return 1 unless$f->()}return 0}sub one (&@) {my$f=shift;my$found=0;for (@_){$f->()and $found++ and return 0}$found}sub any_u (&@) {my$f=shift;return if!@_;$f->()and return 1 foreach (@_);return 0}sub all_u (&@) {my$f=shift;return if!@_;$f->()or return 0 foreach (@_);return 1}sub none_u (&@) {my$f=shift;return if!@_;$f->()and return 0 foreach (@_);return 1}sub notall_u (&@) {my$f=shift;return if!@_;$f->()or return 1 foreach (@_);return 0}sub one_u (&@) {my$f=shift;return if!@_;my$found=0;for (@_){$f->()and $found++ and return 0}$found}sub reduce_u(&@) {my$code=shift;my ($caller_a,$caller_b)=do {my$pkg=caller();no strict 'refs';\*{$pkg .'::a'},\*{$pkg .'::b'}};local (*$caller_a,*$caller_b);*$caller_a=\();for (0 .. $#_){*$caller_b=\$_[$_];*$caller_a=\($code->())}${*$caller_a}}sub reduce_0(&@) {my$code=shift;my ($caller_a,$caller_b)=do {my$pkg=caller();no strict 'refs';\*{$pkg .'::a'},\*{$pkg .'::b'}};local (*$caller_a,*$caller_b);*$caller_a=\0;for (0 .. $#_){*$caller_b=\$_[$_];*$caller_a=\($code->())}${*$caller_a}}sub reduce_1(&@) {my$code=shift;my ($caller_a,$caller_b)=do {my$pkg=caller();no strict 'refs';\*{$pkg .'::a'},\*{$pkg .'::b'}};local (*$caller_a,*$caller_b);*$caller_a=\1;for (0 .. $#_){*$caller_b=\$_[$_];*$caller_a=\($code->())}${*$caller_a}}sub true (&@) {my$f=shift;my$count=0;$f->()and ++$count foreach (@_);return$count}sub false (&@) {my$f=shift;my$count=0;$f->()or ++$count foreach (@_);return$count}sub firstidx (&@) {my$f=shift;for my$i (0 .. $#_){local*_=\$_[$i];return$i if$f->()}return -1}sub firstval (&@) {my$test=shift;for (@_){return $_ if$test->()}return undef}sub firstres (&@) {my$test=shift;for (@_){my$testval=$test->();$testval and return$testval}return undef}sub onlyidx (&@) {my$f=shift;my$found;for my$i (0 .. $#_){local*_=\$_[$i];$f->()or next;defined$found and return -1;$found=$i}return defined$found ? $found : -1}sub onlyval (&@) {my$test=shift;my$result=undef;my$found=0;for (@_){$test->()or next;$result=$_;$found++ and return undef}return$result}sub onlyres (&@) {my$test=shift;my$result=undef;my$found=0;for (@_){my$rv=$test->()or next;$result=$rv;$found++ and return undef}return$found ? $result : undef}sub lastidx (&@) {my$f=shift;for my$i (reverse 0 .. $#_){local*_=\$_[$i];return$i if$f->()}return -1}sub lastval (&@) {my$test=shift;my$ix;for ($ix=$#_;$ix >= 0;$ix--){local*_=\$_[$ix];my$testval=$test->();$_[$ix]=$_;return $_ if$testval}return undef}sub lastres (&@) {my$test=shift;my$ix;for ($ix=$#_;$ix >= 0;$ix--){local*_=\$_[$ix];my$testval=$test->();$_[$ix]=$_;return$testval if$testval}return undef}sub insert_after (&$\@) {my ($f,$val,$list)=@_;my$c=&firstidx($f,@$list);@$list=(@{$list}[0 .. $c],$val,@{$list}[$c + 1 .. $#$list],)and return 1 if$c!=-1;return 0}sub insert_after_string ($$\@) {my ($string,$val,$list)=@_;my$c=firstidx {defined $_ and $string eq $_}@$list;@$list=(@{$list}[0 .. $c],$val,@{$list}[$c + 1 .. $#$list],)and return 1 if$c!=-1;return 0}sub apply (&@) {my$action=shift;&$action foreach my@values=@_;wantarray ? @values : $values[-1]}sub after (&@) {my$test=shift;my$started;my$lag;grep$started ||= do {my$x=$lag;$lag=$test->();$x},@_}sub after_incl (&@) {my$test=shift;my$started;grep$started ||= $test->(),@_}sub before (&@) {my$test=shift;my$more=1;grep$more &&=!$test->(),@_}sub before_incl (&@) {my$test=shift;my$more=1;my$lag=1;grep$more &&= do {my$x=$lag;$lag=!$test->();$x},@_}sub indexes (&@) {my$test=shift;grep {local*_=\$_[$_];$test->()}0 .. $#_}sub pairwise (&\@\@) {my$op=shift;use vars qw{@A @B};local (*A,*B)=@_;my ($caller_a,$caller_b)=do {my$pkg=caller();no strict 'refs';\*{$pkg .'::a'},\*{$pkg .'::b'}};my$limit=$#A > $#B ? $#A : $#B;local (*$caller_a,*$caller_b);map {(*$caller_a,*$caller_b)=\($#A < $_ ? undef : $A[$_],$#B < $_ ? undef : $B[$_]);$op->()}0 .. $limit}sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {return each_arrayref(@_)}sub each_arrayref {my@list=@_;my$index=0;my$max=0;for (@list){unless (ref $_ eq 'ARRAY'){require Carp;Carp::croak("each_arrayref: argument is not an array reference\n")}$max=@$_ if @$_ > $max}return sub {if (@_){my$method=shift;unless ($method eq 'index'){require Carp;Carp::croak("each_array: unknown argument '$method' passed to iterator.")}return undef if$index==0 || $index > $max;return$index - 1}return if$index >= $max;my$i=$index++;return map $_->[$i],@list}}sub natatime ($@) {my$n=shift;my@list=@_;return sub {return splice@list,0,$n}}my$flatten;$flatten=sub {map {(ref $_ and ("ARRAY" eq ref $_ or overload::Method($_,'@{}')))? ($flatten->(@{$_})): ($_)}@_};sub arrayify {map {$flatten->($_)}@_}sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {my$max=-1;$max < $#$_ && ($max=$#$_)foreach @_;map {my$ix=$_;map $_->[$ix],@_}0 .. $max}sub zip6 (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {my$max=-1;$max < $#$_ && ($max=$#$_)foreach @_;map {my$ix=$_;[map $_->[$ix],@_]}0 .. $max}sub listcmp (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {my%ret;for (my$i=0;$i < scalar @_;++$i){my%seen;my$k;for my$w (grep {defined $_ and not $seen{$k=$_}++}@{$_[$i]}){$ret{$w}||= [];push @{$ret{$w}},$i}}%ret}sub uniq (@) {my%seen=();my$k;my$seen_undef;grep {defined $_ ? not $seen{$k=$_}++ : not $seen_undef++}@_}sub singleton (@) {my%seen=();my$k;my$seen_undef;grep {1==(defined $_ ? $seen{$k=$_}: $seen_undef)}grep {defined $_ ? not $seen{$k=$_}++ : not $seen_undef++}@_}sub duplicates (@) {my%seen=();my$k;my$seen_undef;grep {1 < (defined $_ ? $seen{$k=$_}: $seen_undef)}grep {defined $_ ? not $seen{$k=$_}++ : not $seen_undef++}@_}sub frequency (@) {my%seen=();my$k;my$seen_undef;my%h=map {defined $_ ? ($_=>$seen{$k=$_}): ()}grep {defined $_ ? not $seen{$k=$_}++ : not $seen_undef++}@_;wantarray or return (scalar keys%h)+ ($seen_undef ? 1 : 0);undef$k;(%h,$seen_undef ? (\$k=>$seen_undef): ())}sub occurrences (@) {my%seen=();my$k;my$seen_undef;my@ret;for my$l (map {$_}grep {defined $_ ? not $seen{$k=$_}++ : not $seen_undef++}@_){my$n=defined$l ? $seen{$l}: $seen_undef;defined$ret[$n]or $ret[$n]=[];push @{$ret[$n]},$l}@ret}sub mode (@) {my%seen=();my ($max,$k,$seen_undef)=(1);for (@_){defined $_ ? ($max < ++$seen{$k=$_}and ++$max): ($max < ++$seen_undef and ++$max)}wantarray or return$max;my@ret=($max);for my$l (grep {$seen{$_}==$max}keys%seen){push@ret,$l}$seen_undef and $seen_undef==$max and push@ret,undef;@ret}sub samples ($@) {my$n=shift;if ($n > @_){require Carp;Carp::croak(sprintf("Cannot get %d samples from %d elements",$n,scalar @_))}for (my$i=@_;@_ - $i > $n;){my$idx=@_ - $i;my$swp=$idx + int(rand(--$i));my$xchg=$_[$swp];$_[$swp]=$_[$idx];$_[$idx]=$xchg}return splice @_,0,$n}sub minmax (@) {return unless @_;my$min=my$max=$_[0];for (my$i=1;$i < @_;$i += 2){if ($_[$i - 1]<= $_[$i]){$min=$_[$i - 1]if$min > $_[$i - 1];$max=$_[$i]if$max < $_[$i]}else {$min=$_[$i]if$min > $_[$i];$max=$_[$i - 1]if$max < $_[$i - 1]}}if (@_ & 1){my$i=$#_;if ($_[$i - 1]<= $_[$i]){$min=$_[$i - 1]if$min > $_[$i - 1];$max=$_[$i]if$max < $_[$i]}else {$min=$_[$i]if$min > $_[$i];$max=$_[$i - 1]if$max < $_[$i - 1]}}return ($min,$max)}sub minmaxstr (@) {return unless @_;my$min=my$max=$_[0];for (my$i=1;$i < @_;$i += 2){if ($_[$i - 1]le $_[$i]){$min=$_[$i - 1]if$min gt $_[$i - 1];$max=$_[$i]if$max lt $_[$i]}else {$min=$_[$i]if$min gt $_[$i];$max=$_[$i - 1]if$max lt $_[$i - 1]}}if (@_ & 1){my$i=$#_;if ($_[$i - 1]le $_[$i]){$min=$_[$i - 1]if$min gt $_[$i - 1];$max=$_[$i]if$max lt $_[$i]}else {$min=$_[$i]if$min gt $_[$i];$max=$_[$i - 1]if$max lt $_[$i - 1]}}return ($min,$max)}sub part (&@) {my ($code,@list)=@_;my@parts;push @{$parts[$code->($_)]},$_ foreach@list;return@parts}sub bsearch(&@) {my$code=shift;my$rc;my$i=0;my$j=@_;do {my$k=int(($i + $j)/ 2);$k >= @_ and return;local*_=\$_[$k];$rc=$code->();$rc==0 and return wantarray ? $_ : 1;if ($rc < 0){$i=$k + 1}else {$j=$k - 1}}until$i > $j;return}sub bsearchidx(&@) {my$code=shift;my$rc;my$i=0;my$j=@_;do {my$k=int(($i + $j)/ 2);$k >= @_ and return -1;local*_=\$_[$k];$rc=$code->();$rc==0 and return$k;if ($rc < 0){$i=$k + 1}else {$j=$k - 1}}until$i > $j;return -1}sub lower_bound(&@) {my$code=shift;my$count=@_;my$first=0;while ($count > 0){my$step=$count >> 1;my$it=$first + $step;local*_=\$_[$it];if ($code->()< 0){$first=++$it;$count -= $step + 1}else {$count=$step}}$first}sub upper_bound(&@) {my$code=shift;my$count=@_;my$first=0;while ($count > 0){my$step=$count >> 1;my$it=$first + $step;local*_=\$_[$it];if ($code->()<= 0){$first=++$it;$count -= $step + 1}else {$count=$step}}$first}sub equal_range(&@) {my$lb=&lower_bound(@_);my$ub=&upper_bound(@_);($lb,$ub)}sub binsert (&$\@) {my$lb=&lower_bound($_[0],@{$_[2]});splice @{$_[2]},$lb,0,$_[1];$lb}sub bremove (&\@) {my$lb=&lower_bound($_[0],@{$_[1]});splice @{$_[1]},$lb,1}sub qsort(&\@) {require Carp;Carp::croak("It's insane to use a pure-perl qsort")}sub sort_by(&@) {my ($code,@list)=@_;return map {$_->[0]}sort {$a->[1]cmp $b->[1]}map {[$_,scalar($code->())]}@list}sub nsort_by(&@) {my ($code,@list)=@_;return map {$_->[0]}sort {$a->[1]<=> $b->[1]}map {[$_,scalar($code->())]}@list}sub _XScompiled {0}1;
100 LIST_MOREUTILS_PP
101
102 $fatpacked{"List/MoreUtils/XS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIST_MOREUTILS_XS';
103 package List::MoreUtils::XS;use 5.008_001;use strict;use warnings;use base ('Exporter');use vars qw{$VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS};$VERSION='0.428';@EXPORT=();@EXPORT_OK=qw(any all none notall one any_u all_u none_u notall_u one_u reduce_u reduce_0 reduce_1 true false insert_after insert_after_string apply indexes after after_incl before before_incl firstidx lastidx onlyidx firstval lastval onlyval firstres lastres onlyres singleton duplicates frequency occurrences mode each_array each_arrayref pairwise natatime arrayify mesh zip6 uniq listcmp samples minmax minmaxstr part bsearch bsearchidx binsert bremove lower_bound upper_bound equal_range qsort);%EXPORT_TAGS=(all=>\@EXPORT_OK);local$ENV{PERL_DL_NONLAZY}=0 if$ENV{PERL_DL_NONLAZY};use XSLoader ();XSLoader::load("List::MoreUtils::XS","$VERSION");1;
104 LIST_MOREUTILS_XS
105
106 $fatpacked{"Module/Build.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD';
107 package Module::Build;use 5.006;use strict;use warnings;use File::Spec ();use File::Path ();use File::Basename ();use Perl::OSType ();use Module::Build::Base;our@ISA=qw(Module::Build::Base);our$VERSION='0.4224';$VERSION=eval$VERSION;sub _interpose_module {my ($self,$mod)=@_;eval "use $mod";die $@ if $@;no strict 'refs';my$top_class=$mod;while (@{"${top_class}::ISA"}){last if ${"${top_class}::ISA"}[0]eq $ISA[0];$top_class=${"${top_class}::ISA"}[0]}@{"${top_class}::ISA"}=@ISA;@ISA=($mod)}if (grep {-e File::Spec->catfile($_,qw(Module Build Platform),$^O).'.pm'}@INC){__PACKAGE__->_interpose_module("Module::Build::Platform::$^O")}elsif (my$ostype=os_type()){__PACKAGE__->_interpose_module("Module::Build::Platform::$ostype")}else {warn "Unknown OS type '$^O' - using default settings\n"}sub os_type {return Perl::OSType::os_type()}sub is_vmsish {return Perl::OSType::is_os_type('VMS')}sub is_windowsish {return Perl::OSType::is_os_type('Windows')}sub is_unixish {return Perl::OSType::is_os_type('Unix')}1;
108 MODULE_BUILD
109
110 $fatpacked{"Module/Build/Base.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_BASE';
111 package Module::Build::Base;use 5.006;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Carp;use Cwd ();use File::Copy ();use File::Find ();use File::Path ();use File::Basename ();use File::Spec 0.82 ();use File::Compare ();use Module::Build::Dumper ();use Text::ParseWords ();use Module::Metadata;use Module::Build::Notes;use Module::Build::Config;use version;sub new {my$self=shift()->_construct(@_);$self->{invoked_action}=$self->{action}||= 'Build_PL';$self->cull_args(@ARGV);die "Too early to specify a build action '$self->{action}'. Do 'Build $self->{action}' instead.\n" if$self->{action}&& $self->{action}ne 'Build_PL';$self->check_manifest;$self->auto_require;if(grep {!$_}$self->check_prereq,$self->check_autofeatures){$self->log_warn(<<EOF);unless ($self->dist_name eq 'Module-Build' || $ENV{PERL5_CPANPLUS_IS_RUNNING}|| $ENV{PERL5_CPAN_IS_RUNNING}){$self->log_warn("Run 'Build installdeps' to install missing prerequisites.\n\n")}}$self->{properties}{_added_to_INC}=[$self->_added_to_INC ];$self->set_bundle_inc;$self->dist_name;$self->dist_version;$self->release_status;$self->_guess_module_name unless$self->module_name;$self->_find_nested_builds;return$self}sub resume {my$package=shift;my$self=$package->_construct(@_);$self->read_config;my@added_earlier=@{$self->{properties}{_added_to_INC}|| []};@INC=($self->_added_to_INC,@added_earlier,$self->_default_INC);unless ($package->isa($self->build_class)){my$build_class=$self->build_class;my$config_dir=$self->config_dir || '_build';my$build_lib=File::Spec->catdir($config_dir,'lib');unshift(@INC,$build_lib);unless ($build_class->can('new')){eval "require $build_class; 1" or die "Failed to re-load '$build_class': $@"}return$build_class->resume(@_)}unless ($self->_perl_is_same($self->{properties}{perl})){my$perl=$self->find_perl_interpreter;die(<<"DIEFATAL")}$self->cull_args(@ARGV);unless ($self->allow_mb_mismatch){my$mb_version=$Module::Build::VERSION;if ($mb_version ne $self->{properties}{mb_version}){$self->log_warn(<<"MISMATCH")}}$self->{invoked_action}=$self->{action}||= 'build';return$self}sub new_from_context {my ($package,%args)=@_;$package->run_perl_script('Build.PL',[],[$package->unparse_args(\%args)]);return$package->resume}sub current {local@ARGV;return shift()->resume}sub _construct {my ($package,%input)=@_;my$args=delete$input{args}|| {};my$config=delete$input{config}|| {};my$self=bless {args=>{%$args},config=>Module::Build::Config->new(values=>$config),properties=>{base_dir=>$package->cwd,mb_version=>$Module::Build::VERSION,%input,},phash=>{},stash=>{},},$package;$self->_set_defaults;my ($p,$ph)=($self->{properties},$self->{phash});for (qw(notes config_data features runtime_params cleanup auto_features)){my$file=File::Spec->catfile($self->config_dir,$_);$ph->{$_}=Module::Build::Notes->new(file=>$file);$ph->{$_}->restore if -e $file;if (exists$p->{$_}){my$vals=delete$p->{$_};for my$k (sort keys %$vals){$self->$_($k,$vals->{$k})}}}$p->{perl}=$self->find_perl_interpreter or $self->log_warn("Warning: Can't locate your perl binary");my$blibdir=sub {File::Spec->catdir($p->{blib},@_)};$p->{bindoc_dirs}||= [$blibdir->("script")];$p->{libdoc_dirs}||= [$blibdir->("lib"),$blibdir->("arch")];$p->{dist_author}=[$p->{dist_author}]if defined$p->{dist_author}and not ref$p->{dist_author};$p->{requires}=delete$p->{prereq}if defined$p->{prereq};$p->{script_files}=delete$p->{scripts}if defined$p->{scripts};for ('extra_compiler_flags','extra_linker_flags'){$p->{$_}=[$self->split_like_shell($p->{$_})]if exists$p->{$_}}for ('include_dirs'){$p->{$_}=[$p->{$_}]if exists$p->{$_}&&!ref$p->{$_}}$self->add_to_cleanup(@{delete$p->{add_to_cleanup}})if$p->{add_to_cleanup};return$self}sub log_info {my$self=shift;print @_ if ref($self)&& ($self->verbose ||!$self->quiet)}sub log_verbose {my$self=shift;print @_ if ref($self)&& $self->verbose}sub log_debug {my$self=shift;print @_ if ref($self)&& $self->debug}sub log_warn {shift;if (@_ and $_[-1]!~ /\n$/){my (undef,$file,$line)=caller();warn @_," at $file line $line.\n"}else {warn @_}}sub _default_install_paths {my$self=shift;my$c=$self->{config};my$p={};my@libstyle=$c->get('installstyle')? File::Spec->splitdir($c->get('installstyle')): qw(lib perl5);my$arch=$c->get('archname');my$version=$c->get('version');my$bindoc=$c->get('installman1dir')|| undef;my$libdoc=$c->get('installman3dir')|| undef;my$binhtml=$c->get('installhtml1dir')|| $c->get('installhtmldir')|| undef;my$libhtml=$c->get('installhtml3dir')|| $c->get('installhtmldir')|| undef;$p->{install_sets}={core=>{lib=>$c->get('installprivlib'),arch=>$c->get('installarchlib'),bin=>$c->get('installbin'),script=>$c->get('installscript'),bindoc=>$bindoc,libdoc=>$libdoc,binhtml=>$binhtml,libhtml=>$libhtml,},site=>{lib=>$c->get('installsitelib'),arch=>$c->get('installsitearch'),bin=>$c->get('installsitebin')|| $c->get('installbin'),script=>$c->get('installsitescript')|| $c->get('installsitebin')|| $c->get('installscript'),bindoc=>$c->get('installsiteman1dir')|| $bindoc,libdoc=>$c->get('installsiteman3dir')|| $libdoc,binhtml=>$c->get('installsitehtml1dir')|| $binhtml,libhtml=>$c->get('installsitehtml3dir')|| $libhtml,},vendor=>{lib=>$c->get('installvendorlib'),arch=>$c->get('installvendorarch'),bin=>$c->get('installvendorbin')|| $c->get('installbin'),script=>$c->get('installvendorscript')|| $c->get('installvendorbin')|| $c->get('installscript'),bindoc=>$c->get('installvendorman1dir')|| $bindoc,libdoc=>$c->get('installvendorman3dir')|| $libdoc,binhtml=>$c->get('installvendorhtml1dir')|| $binhtml,libhtml=>$c->get('installvendorhtml3dir')|| $libhtml,},};$p->{original_prefix}={core=>$c->get('installprefixexp')|| $c->get('installprefix')|| $c->get('prefixexp')|| $c->get('prefix')|| '',site=>$c->get('siteprefixexp'),vendor=>$c->get('usevendorprefix')? $c->get('vendorprefixexp'): '',};$p->{original_prefix}{site}||= $p->{original_prefix}{core};$p->{install_base_relpaths}={lib=>['lib','perl5'],arch=>['lib','perl5',$arch],bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],};$p->{prefix_relpaths}={core=>{lib=>[@libstyle],arch=>[@libstyle,$version,$arch],bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],},vendor=>{lib=>[@libstyle],arch=>[@libstyle,$version,$arch],bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],},site=>{lib=>[@libstyle,'site_perl'],arch=>[@libstyle,'site_perl',$version,$arch],bin=>['bin'],script=>['bin'],bindoc=>['man','man1'],libdoc=>['man','man3'],binhtml=>['html'],libhtml=>['html'],},};return$p}sub _find_nested_builds {my$self=shift;my$r=$self->recurse_into or return;my ($file,@r);if (!ref($r)&& $r eq 'auto'){local*DH;opendir DH,$self->base_dir or die "Can't scan directory " .$self->base_dir ." for nested builds: $!";while (defined($file=readdir DH)){my$subdir=File::Spec->catdir($self->base_dir,$file);next unless -d $subdir;push@r,$subdir if -e File::Spec->catfile($subdir,'Build.PL')}}$self->recurse_into(\@r)}sub cwd {return Cwd::cwd()}sub _quote_args {my ($self,@args)=@_;my@quoted;for (@args){if (/^[^\s*?!\$<>;\\|'"\[\]\{\}]+$/){push@quoted,$_}else {s/('+)/'"$1"'/g;push@quoted,qq('$_')}}return join " ",@quoted}sub _backticks {my ($self,@cmd)=@_;if ($self->have_forkpipe){local*FH;my$pid=open*FH,"-|";if ($pid){return wantarray ? <FH> : join '',<FH>}else {die "Can't execute @cmd: $!\n" unless defined$pid;exec {$cmd[0]}@cmd}}else {my$cmd=$self->_quote_args(@cmd);return `$cmd`}}sub have_forkpipe {1}sub _perl_is_same {my ($self,$perl)=@_;my@cmd=($perl);if ($ENV{PERL_CORE}){push@cmd,'-I' .File::Spec->catdir(File::Basename::dirname($perl),'lib')}push@cmd,qw(-MConfig=myconfig -e print -e myconfig);return$self->_backticks(@cmd)eq Config->myconfig}{my$known_perl;sub find_perl_interpreter {my$self=shift;return$known_perl if defined($known_perl);return$known_perl=$self->_discover_perl_interpreter}}sub _discover_perl_interpreter {my$proto=shift;my$c=ref($proto)? $proto->{config}: 'Module::Build::Config';my$perl=$^X;my$perl_basename=File::Basename::basename($perl);my@potential_perls;push(@potential_perls,$perl)if File::Spec->file_name_is_absolute($perl);my$abs_perl=File::Spec->rel2abs($perl);push(@potential_perls,$abs_perl);if ($ENV{PERL_CORE}){require ExtUtils::CBuilder;my$perl_src=Cwd::realpath(ExtUtils::CBuilder->perl_src);if (defined($perl_src)&& length($perl_src)){my$uninstperl=File::Spec->rel2abs(File::Spec->catfile($perl_src,$perl_basename));push(@potential_perls,$uninstperl)}}else {push(@potential_perls,$c->get('perlpath'));push(@potential_perls,map File::Spec->catfile($_,$perl_basename),File::Spec->path())}my$exe=$c->get('exe_ext');for my$thisperl (@potential_perls){if (defined$exe){$thisperl .= $exe unless$thisperl =~ m/$exe$/i}if (-f $thisperl && $proto->_perl_is_same($thisperl)){return$thisperl}}my@paths=map File::Basename::dirname($_),@potential_perls;die "Can't locate the perl binary used to run this script " ."in (@paths)\n"}sub find_command {my ($self,$command)=@_;if(File::Spec->file_name_is_absolute($command)){return$self->_maybe_command($command)}else {for my$dir (File::Spec->path){my$abs=File::Spec->catfile($dir,$command);return$abs if$abs=$self->_maybe_command($abs)}}}sub _maybe_command {my($self,$file)=@_;return$file if -x $file &&!-d $file;return}sub _is_interactive {return -t STDIN && (-t STDOUT ||!(-f STDOUT || -c STDOUT))}sub _is_unattended {my$self=shift;return$ENV{PERL_MM_USE_DEFAULT}|| (!$self->_is_interactive && eof STDIN)}sub _readline {my$self=shift;return undef if$self->_is_unattended;my$answer=<STDIN>;chomp$answer if defined$answer;return$answer}sub prompt {my$self=shift;my$mess=shift or die "prompt() called without a prompt message";my@def;@def=(shift)if @_;my@dispdef=scalar(@def)? ('[',(defined($def[0])? $def[0].' ' : ''),']'): (' ','');local $|=1;print "$mess ",@dispdef;if ($self->_is_unattended &&!@def){die <<EOF}my$ans=$self->_readline();if (!defined($ans)or!length($ans)){print "$dispdef[1]\n";$ans=scalar(@def)? $def[0]: ''}return$ans}sub y_n {my$self=shift;my ($mess,$def)=@_;die "y_n() called without a prompt message" unless$mess;die "Invalid default value: y_n() default must be 'y' or 'n'" if$def && $def !~ /^[yn]/i;my$answer;while (1){$answer=$self->prompt(@_);return 1 if$answer =~ /^y/i;return 0 if$answer =~ /^n/i;local $|=1;print "Please answer 'y' or 'n'.\n"}}sub current_action {shift->{action}}sub invoked_action {shift->{invoked_action}}sub notes {shift()->{phash}{notes}->access(@_)}sub config_data {shift()->{phash}{config_data}->access(@_)}sub runtime_params {shift->{phash}{runtime_params}->read(@_ ? shift : ())}sub auto_features {shift()->{phash}{auto_features}->access(@_)}sub features {my$self=shift;my$ph=$self->{phash};if (@_){my$key=shift;if ($ph->{features}->exists($key)){return$ph->{features}->access($key,@_)}if (my$info=$ph->{auto_features}->access($key)){my$disabled;for my$type (@{$self->prereq_action_types}){next if$type eq 'description' || $type eq 'recommends' ||!exists$info->{$type};my$prereqs=$info->{$type};for my$modname (sort keys %$prereqs){my$spec=$prereqs->{$modname};my$status=$self->check_installed_status($modname,$spec);if ((!$status->{ok})xor ($type =~ /conflicts$/)){return 0}if (!eval "require $modname; 1"){return 0}}}return 1}return$ph->{features}->access($key,@_)}my%features;my%auto_features=$ph->{auto_features}->access();while (my ($name,$info)=each%auto_features){my$failures=$self->prereq_failures($info);my$disabled=grep(/^(?:\w+_)?(?:requires|conflicts)$/,keys %$failures)? 1 : 0;$features{$name}=$disabled ? 0 : 1}%features=(%features,$ph->{features}->access());return wantarray ? %features : \%features}BEGIN {*feature=\&features}sub _mb_feature {my$self=shift;if (($self->module_name || '')eq 'Module::Build'){return$self->feature(@_)}else {require Module::Build::ConfigData;return Module::Build::ConfigData->feature(@_)}}sub _warn_mb_feature_deps {my$self=shift;my$name=shift;$self->log_warn("The '$name' feature is not available. Please install missing\n" ."feature dependencies and try again.\n".$self->_feature_deps_msg($name)."\n")}sub add_build_element {my ($self,$elem)=@_;my$elems=$self->build_elements;push @$elems,$elem unless grep {$_ eq $elem}@$elems}sub ACTION_config_data {my$self=shift;return unless$self->has_config_data;my$module_name=$self->module_name or die "The config_data feature requires that 'module_name' be set";my$notes_name=$module_name .'::ConfigData';my$notes_pm=File::Spec->catfile($self->blib,'lib',split /::/,"$notes_name.pm");return if$self->up_to_date(['Build.PL',$self->config_file('config_data'),$self->config_file('features')],$notes_pm);$self->log_verbose("Writing config notes to $notes_pm\n");File::Path::mkpath(File::Basename::dirname($notes_pm));Module::Build::Notes->write_config_data (file=>$notes_pm,module=>$module_name,config_module=>$notes_name,config_data=>scalar$self->config_data,feature=>scalar$self->{phash}{features}->access(),auto_features=>scalar$self->auto_features,)}{my%valid_properties=(__PACKAGE__,{});my%additive_properties;sub _mb_classes {my$class=ref($_[0])|| $_[0];return ($class,$class->mb_parents)}sub valid_property {my ($class,$prop)=@_;return grep exists($valid_properties{$_}{$prop}),$class->_mb_classes}sub valid_properties {return keys %{shift->valid_properties_defaults()}}sub valid_properties_defaults {my%out;for my$class (reverse shift->_mb_classes){@out{keys %{$valid_properties{$class}}}=map {$_->()}values %{$valid_properties{$class}}}return \%out}sub array_properties {map {exists$additive_properties{$_}->{ARRAY}? @{$additive_properties{$_}->{ARRAY}}: ()}shift->_mb_classes}sub hash_properties {map {exists$additive_properties{$_}->{HASH}? @{$additive_properties{$_}->{HASH}}: ()}shift->_mb_classes}sub add_property {my ($class,$property)=(shift,shift);die "Property '$property' already exists" if$class->valid_property($property);my%p=@_==1 ? (default=>shift): @_;my$type=ref$p{default};$valid_properties{$class}{$property}=$type eq 'CODE' ? $p{default}: $type eq 'HASH' ? sub {return {%{$p{default}}}}: $type eq 'ARRAY'? sub {return [@{$p{default}}]}: sub {return$p{default}};push @{$additive_properties{$class}->{$type}},$property if$type;unless ($class->can($property)){my$sub=$type eq 'HASH' ? _make_hash_accessor($property,\%p): _make_accessor($property,\%p);no strict 'refs';*{"$class\::$property"}=$sub}return$class}sub property_error {my$self=shift;die 'ERROR: ',@_}sub _set_defaults {my$self=shift;$self->{properties}{build_class}||= ref$self;$self->{properties}{orig_dir}||= $self->{properties}{base_dir};my$defaults=$self->valid_properties_defaults;for my$prop (keys %$defaults){$self->{properties}{$prop}=$defaults->{$prop}unless exists$self->{properties}{$prop}}for my$prop ($self->array_properties){$self->{properties}{$prop}=[@{$defaults->{$prop}}]unless exists$self->{properties}{$prop}}for my$prop ($self->hash_properties){$self->{properties}{$prop}={%{$defaults->{$prop}}}unless exists$self->{properties}{$prop}}}}sub _make_hash_accessor {my ($property,$p)=@_;my$check=$p->{check}|| sub {1};return sub {my$self=shift;unless(ref($self)){carp("\n$property not a class method (@_)");return}my$x=$self->{properties};return$x->{$property}unless @_;my$prop=$x->{$property};if (defined $_[0]&&!ref $_[0]){if (@_==1){return exists$prop->{$_[0]}? $prop->{$_[0]}: undef}elsif (@_ % 2==0){my%new=(%{$prop},@_);local $_=\%new;$x->{$property}=\%new if$check->($self);return$x->{$property}}else {die "Unexpected arguments for property '$property'\n"}}else {die "Unexpected arguments for property '$property'\n" if defined $_[0]&& ref $_[0]ne 'HASH';local $_=$_[0];$x->{$property}=shift if$check->($self)}}}sub _make_accessor {my ($property,$p)=@_;my$check=$p->{check}|| sub {1};return sub {my$self=shift;unless(ref($self)){carp("\n$property not a class method (@_)");return}my$x=$self->{properties};return$x->{$property}unless @_;local $_=$_[0];$x->{$property}=shift if$check->($self);return$x->{$property}}}__PACKAGE__->add_property(auto_configure_requires=>1);__PACKAGE__->add_property(blib=>'blib');__PACKAGE__->add_property(build_class=>'Module::Build');__PACKAGE__->add_property(build_elements=>[qw(PL support pm xs share_dir pod script)]);__PACKAGE__->add_property(build_script=>'Build');__PACKAGE__->add_property(build_bat=>0);__PACKAGE__->add_property(bundle_inc=>[]);__PACKAGE__->add_property(bundle_inc_preload=>[]);__PACKAGE__->add_property(config_dir=>'_build');__PACKAGE__->add_property(dynamic_config=>1);__PACKAGE__->add_property(include_dirs=>[]);__PACKAGE__->add_property(license=>'unknown');__PACKAGE__->add_property(metafile=>'META.yml');__PACKAGE__->add_property(mymetafile=>'MYMETA.yml');__PACKAGE__->add_property(metafile2=>'META.json');__PACKAGE__->add_property(mymetafile2=>'MYMETA.json');__PACKAGE__->add_property(recurse_into=>[]);__PACKAGE__->add_property(use_rcfile=>1);__PACKAGE__->add_property(create_packlist=>1);__PACKAGE__->add_property(allow_mb_mismatch=>0);__PACKAGE__->add_property(config=>undef);__PACKAGE__->add_property(test_file_exts=>['.t']);__PACKAGE__->add_property(use_tap_harness=>0);__PACKAGE__->add_property(cpan_client=>'cpan');__PACKAGE__->add_property(tap_harness_args=>{});__PACKAGE__->add_property(pureperl_only=>0);__PACKAGE__->add_property(allow_pureperl=>0);__PACKAGE__->add_property('installdirs',default=>'site',check=>sub {return 1 if /^(core|site|vendor)$/;return shift->property_error($_ eq 'perl' ? 'Perhaps you meant installdirs to be "core" rather than "perl"?' : 'installdirs must be one of "core", "site", or "vendor"');return shift->property_error("Perhaps you meant 'core'?")if $_ eq 'perl';return 0},);{__PACKAGE__->add_property(html_css=>'')}{my@prereq_action_types=qw(requires build_requires test_requires conflicts recommends);for my$type (@prereq_action_types){__PACKAGE__->add_property($type=>{})}__PACKAGE__->add_property(prereq_action_types=>\@prereq_action_types)}__PACKAGE__->add_property($_=>{})for qw(get_options install_base_relpaths install_path install_sets meta_add meta_merge original_prefix prefix_relpaths configure_requires);__PACKAGE__->add_property($_)for qw(PL_files autosplit base_dir bindoc_dirs c_source cover create_license create_makefile_pl create_readme debugger destdir dist_abstract dist_author dist_name dist_suffix dist_version dist_version_from extra_compiler_flags extra_linker_flags has_config_data install_base libdoc_dirs magic_number mb_version module_name needs_compiler orig_dir perl pm_files pod_files pollute prefix program_name quiet recursive_test_files release_status script_files scripts share_dir sign test_files verbose debug xs_files extra_manify_args);sub config {my$self=shift;my$c=ref($self)? $self->{config}: 'Module::Build::Config';return$c->all_config unless @_;my$key=shift;return$c->get($key)unless @_;my$val=shift;return$c->set($key=>$val)}sub mb_parents {my@in_stack=(shift);my%seen=($in_stack[0]=>1);my ($current,@out);while (@in_stack){next unless defined($current=shift@in_stack)&& $current->isa('Module::Build::Base');push@out,$current;next if$current eq 'Module::Build::Base';no strict 'refs';unshift@in_stack,map {my$c=$_;substr($c,0,2)="main::" if substr($c,0,2)eq '::';$seen{$c}++ ? (): $c}@{"$current\::ISA"}}shift@out;return@out}sub extra_linker_flags {shift->_list_accessor('extra_linker_flags',@_)}sub extra_compiler_flags {shift->_list_accessor('extra_compiler_flags',@_)}sub _list_accessor {(my$self,local $_)=(shift,shift);my$p=$self->{properties};$p->{$_}=[@_]if @_;$p->{$_}=[]unless exists$p->{$_};return ref($p->{$_})? $p->{$_}: [$p->{$_}]}sub subclass {my ($pack,%opts)=@_;my$build_dir='_build';$pack->delete_filetree($build_dir)if -e $build_dir;die "Must provide 'code' or 'class' option to subclass()\n" unless$opts{code}or $opts{class};$opts{code}||= '';$opts{class}||= 'MyModuleBuilder';my$filename=File::Spec->catfile($build_dir,'lib',split '::',$opts{class}).'.pm';my$filedir=File::Basename::dirname($filename);$pack->log_verbose("Creating custom builder $filename in $filedir\n");File::Path::mkpath($filedir);die "Can't create directory $filedir: $!" unless -d $filedir;open(my$fh,'>',$filename)or die "Can't create $filename: $!";print$fh <<EOF;close$fh;unshift@INC,File::Spec->catdir(File::Spec->rel2abs($build_dir),'lib');eval "use $opts{class}";die $@ if $@;return$opts{class}}sub _guess_module_name {my$self=shift;my$p=$self->{properties};return if$p->{module_name};if ($p->{dist_version_from}&& -e $p->{dist_version_from}){my$mi=Module::Metadata->new_from_file($self->dist_version_from);$p->{module_name}=$mi->name}else {my$mod_path=my$mod_name=$p->{dist_name};$mod_name =~ s{-}{::}g;$mod_path =~ s{-}{/}g;$mod_path .= ".pm";if (-e $mod_path || -e "lib/$mod_path"){$p->{module_name}=$mod_name}else {$self->log_warn(<< 'END_WARN')}}}sub dist_name {my$self=shift;my$p=$self->{properties};my$me='dist_name';return$p->{$me}if defined$p->{$me};die "Can't determine distribution name, must supply either 'dist_name' or 'module_name' parameter" unless$self->module_name;($p->{$me}=$self->module_name)=~ s/::/-/g;return$p->{$me}}sub release_status {my ($self)=@_;my$me='release_status';my$p=$self->{properties};if (!defined$p->{$me}){$p->{$me}=$self->_is_dev_version ? 'testing' : 'stable'}unless ($p->{$me}=~ qr/\A(?:stable|testing|unstable)\z/){die "Illegal value '$p->{$me}' for $me\n"}if ($p->{$me}eq 'stable' && $self->_is_dev_version){my$version=$self->dist_version;die "Illegal value '$p->{$me}' with version '$version'\n"}return$p->{$me}}sub dist_suffix {my ($self)=@_;my$p=$self->{properties};my$me='dist_suffix';return$p->{$me}if defined$p->{$me};if ($self->release_status eq 'stable'){$p->{$me}=""}else {$p->{$me}=$self->_is_dev_version ? "" : "TRIAL" }return$p->{$me}}sub dist_version_from {my ($self)=@_;my$p=$self->{properties};my$me='dist_version_from';if ($self->module_name){$p->{$me}||= join('/','lib',split(/::/,$self->module_name)).'.pm'}return$p->{$me}|| undef}sub dist_version {my ($self)=@_;my$p=$self->{properties};my$me='dist_version';return$p->{$me}if defined$p->{$me};if (my$dist_version_from=$self->dist_version_from){my$version_from=File::Spec->catfile(split(qr{/},$dist_version_from));my$pm_info=Module::Metadata->new_from_file($version_from)or die "Can't find file $version_from to determine version";$p->{$me}=$self->normalize_version($pm_info->version());unless (defined$p->{$me}){die "Can't determine distribution version from $version_from"}}die ("Can't determine distribution version, must supply either 'dist_version',\n"."'dist_version_from', or 'module_name' parameter")unless defined$p->{$me};return$p->{$me}}sub _is_dev_version {my ($self)=@_;my$dist_version=$self->dist_version;my$version_obj=eval {version->new($dist_version)};return $@ ? 0 : $version_obj->is_alpha}sub dist_author {shift->_pod_parse('author')}sub dist_abstract {shift->_pod_parse('abstract')}sub _pod_parse {my ($self,$part)=@_;my$p=$self->{properties};my$member="dist_$part";return$p->{$member}if defined$p->{$member};my$docfile=$self->_main_docfile or return;open(my$fh,'<',$docfile)or return;require Module::Build::PodParser;my$parser=Module::Build::PodParser->new(fh=>$fh);my$method="get_$part";return$p->{$member}=$parser->$method()}sub version_from_file {return Module::Metadata->new_from_file($_[1])->version()}sub find_module_by_name {return Module::Metadata->find_module_by_name(@_[1,2])}{my%unlink_list_for_pid;sub _unlink_on_exit {my$self=shift;for my$f (@_){push @{$unlink_list_for_pid{$$}},$f if -f $f}return 1}END {for my$f (map glob($_),@{$unlink_list_for_pid{$$}|| []}){next unless -e $f;File::Path::rmtree($f,0,0)}}}sub add_to_cleanup {my$self=shift;my%files=map {$self->localize_file_path($_),1}@_;$self->{phash}{cleanup}->write(\%files)}sub cleanup {my$self=shift;my$all=$self->{phash}{cleanup}->read;return wantarray ? sort keys %$all : keys %$all}sub config_file {my$self=shift;return unless -d $self->config_dir;return File::Spec->catfile($self->config_dir,@_)}sub read_config {my ($self)=@_;my$file=$self->config_file('build_params')or die "Can't find 'build_params' in " .$self->config_dir;open(my$fh,'<',$file)or die "Can't read '$file': $!";my$ref=eval do {local $/;<$fh>};die if $@;close$fh;my$c;($self->{args},$c,$self->{properties})=@$ref;$self->{config}=Module::Build::Config->new(values=>$c)}sub has_config_data {my$self=shift;return scalar grep$self->{phash}{$_}->has_data(),qw(config_data features auto_features)}sub _write_data {my ($self,$filename,$data)=@_;my$file=$self->config_file($filename);open(my$fh,'>',$file)or die "Can't create '$file': $!";unless (ref($data)){print$fh $data;return}print {$fh}Module::Build::Dumper->_data_dump($data);close$fh}sub write_config {my ($self)=@_;File::Path::mkpath($self->{properties}{config_dir});-d $self->{properties}{config_dir}or die "Can't mkdir $self->{properties}{config_dir}: $!";my@items=@{$self->prereq_action_types};$self->_write_data('prereqs',{map {$_,$self->$_()}@items });$self->_write_data('build_params',[$self->{args},$self->{config}->values_set,$self->{properties}]);$self->_write_data('magicnum',$self->magic_number(int rand 1_000_000));$self->{phash}{$_}->write()foreach qw(notes cleanup features auto_features config_data runtime_params)}{my%packlist_map=('^File::Spec'=>'Cwd','^Devel::AssertOS'=>'Devel::CheckOS',);sub _find_packlist {my ($self,$inst,$mod)=@_;my$lookup=$mod;my$packlist=eval {$inst->packlist($lookup)};if (!$packlist){while (my ($re,$new_mod)=each%packlist_map){if ($mod =~ qr/$re/){$lookup=$new_mod;$packlist=eval {$inst->packlist($lookup)};last}}}return$packlist ? $lookup : undef}sub set_bundle_inc {my$self=shift;my$bundle_inc=$self->{properties}{bundle_inc};my$bundle_inc_preload=$self->{properties}{bundle_inc_preload};return unless inc::latest->can('loaded_modules');require ExtUtils::Installed;my$inst=eval {ExtUtils::Installed->new(extra_libs=>[@INC])};if ($@){$self->log_warn(<< "EUI_ERROR");return}my@bundle_list=map {[$_,0 ]}inc::latest->loaded_modules;while(@bundle_list){my ($mod,$prereq)=@{shift@bundle_list};my$lookup=$self->_find_packlist($inst,$mod);if (!$lookup){die << "NO_PACKLIST"}else {push @{$prereq ? $bundle_inc_preload : $bundle_inc},$lookup}}}}sub check_autofeatures {my ($self)=@_;my$features=$self->auto_features;return 1 unless %$features;my$longest=sub {my@str=@_ or croak("no strings given");my@len=map({length($_)}@str);my$max=0;my$longest;for my$i (0..$#len){($max,$longest)=($len[$i],$str[$i])if($len[$i]> $max)}return($longest)};my$max_name_len=length($longest->(keys %$features));my ($num_disabled,$log_text)=(0,"\nChecking optional features...\n");for my$name (sort keys %$features){$log_text .= $self->_feature_deps_msg($name,$max_name_len)}$num_disabled=()=$log_text =~ /disabled/g;if ($num_disabled){$self->log_warn($log_text);return 0}else {$self->log_verbose($log_text);return 1}}sub _feature_deps_msg {my ($self,$name,$max_name_len)=@_;$max_name_len ||= length$name;my$features=$self->auto_features;my$info=$features->{$name};my$feature_text="$name" .'.' x ($max_name_len - length($name)+ 4);my ($log_text,$disabled)=('','');if (my$failures=$self->prereq_failures($info)){$disabled=grep(/^(?:\w+_)?(?:requires|conflicts)$/,keys %$failures)? 1 : 0;$feature_text .= $disabled ? "disabled\n" : "enabled\n";for my$type (@{$self->prereq_action_types}){next unless exists$failures->{$type};$feature_text .= " $type:\n";my$prereqs=$failures->{$type};for my$module (sort keys %$prereqs){my$status=$prereqs->{$module};my$required=($type =~ /^(?:\w+_)?(?:requires|conflicts)$/)? 1 : 0;my$prefix=($required)? '!' : '*';$feature_text .= " $prefix $status->{message}\n"}}}else {$feature_text .= "enabled\n"}$log_text .= $feature_text if$disabled || $self->verbose;return$log_text}sub auto_config_requires {my ($self)=@_;my$p=$self->{properties};if ($self->dist_name ne 'Module-Build' && $self->auto_configure_requires &&!exists$p->{configure_requires}{'Module::Build'}){(my$ver=$VERSION)=~ s/^(\d+\.\d\d).*$/$1/;$self->log_warn(<<EOM);$self->_add_prereq('configure_requires','Module::Build',$ver)}if (inc::latest->can('loaded_module')){for my$mod (inc::latest->loaded_modules){next if exists$p->{configure_requires}{$mod};$self->_add_prereq('configure_requires',$mod,$mod->VERSION)}}return}sub auto_require {my ($self)=@_;my$p=$self->{properties};my$xs_files=$self->find_xs_files;if (!defined$p->{needs_compiler}){$self->needs_compiler(keys %$xs_files || defined$self->c_source)}if ($self->needs_compiler){$self->_add_prereq('build_requires','ExtUtils::CBuilder',0);if (!$self->have_c_compiler){$self->log_warn(<<'EOM')}}if ($self->share_dir){$self->_add_prereq('requires','File::ShareDir','1.00')}return}sub _add_prereq {my ($self,$type,$module,$version)=@_;my$p=$self->{properties};$version=0 unless defined$version;if (exists$p->{$type}{$module}){return if$self->compare_versions($version,'<=',$p->{$type}{$module})}$self->log_verbose("Adding to $type\: $module => $version\n");$p->{$type}{$module}=$version;return 1}sub prereq_failures {my ($self,$info)=@_;my@types=@{$self->prereq_action_types};$info ||= {map {$_,$self->$_()}@types};my$out;for my$type (@types){my$prereqs=$info->{$type};for my$modname (keys %$prereqs){my$spec=$prereqs->{$modname};my$status=$self->check_installed_status($modname,$spec);if ($type =~ /^(?:\w+_)?conflicts$/){next if!$status->{ok};$status->{conflicts}=delete$status->{need};$status->{message}="$modname ($status->{have}) conflicts with this distribution"}elsif ($type =~ /^(?:\w+_)?recommends$/){next if$status->{ok};$status->{message}=(!ref($status->{have})&& $status->{have}eq '<none>' ? "$modname is not installed" : "$modname ($status->{have}) is installed, but we prefer to have $spec")}else {next if$status->{ok}}$out->{$type}{$modname}=$status}}return$out}sub _enum_prereqs {my$self=shift;my%prereqs;for my$type (@{$self->prereq_action_types}){if ($self->can($type)){my$prereq=$self->$type()|| {};$prereqs{$type}=$prereq if %$prereq}}return \%prereqs}sub check_prereq {my$self=shift;my$info=$self->_enum_prereqs;return 1 unless$info;my$log_text="Checking prerequisites...\n";my$failures=$self->prereq_failures($info);if ($failures){$self->log_warn($log_text);for my$type (@{$self->prereq_action_types}){my$prereqs=$failures->{$type};$self->log_warn(" ${type}:\n")if keys %$prereqs;for my$module (sort keys %$prereqs){my$status=$prereqs->{$module};my$prefix=($type =~ /^(?:\w+_)?recommends$/)? "* " : "! ";$self->log_warn(" $prefix $status->{message}\n")}}return 0}else {$self->log_verbose($log_text ."Looks good\n\n");return 1}}sub perl_version {my ($self)=@_;return $^V ? $self->perl_version_to_float(sprintf "%vd",$^V): $]}sub perl_version_to_float {my ($self,$version)=@_;return$version if grep(/\./,$version)< 2;$version =~ s/\./../;$version =~ s/\.(\d+)/sprintf '%03d', $1/eg;return$version}sub _parse_conditions {my ($self,$spec)=@_;return ">= 0" if not defined$spec;if ($spec =~ /^\s*([\w.]+)\s*$/){return (">= $spec")}else {return split /\s*,\s*/,$spec}}sub try_require {my ($self,$modname,$spec)=@_;my$status=$self->check_installed_status($modname,defined($spec)? $spec : 0);return unless$status->{ok};my$path=$modname;$path =~ s{::}{/}g;$path .= ".pm";if (defined$INC{$path}){return 1}elsif (exists$INC{$path}){return}else {return eval "require $modname"}}sub check_installed_status {my ($self,$modname,$spec)=@_;my%status=(need=>$spec);if ($modname eq 'perl'){$status{have}=$self->perl_version}elsif (eval {no strict;$status{have}=${"${modname}::VERSION"}}){}else {my$pm_info=Module::Metadata->new_from_module($modname);unless (defined($pm_info)){@status{qw(have message) }=('<none>',"$modname is not installed");return \%status}$status{have}=eval {$pm_info->version()};if ($spec and!defined($status{have})){@status{qw(have message) }=(undef,"Couldn't find a \$VERSION in prerequisite $modname");return \%status}}my@conditions=$self->_parse_conditions($spec);for (@conditions){my ($op,$version)=/^\s* (<=?|>=?|==|!=) \s* ([\w.]+) \s*$/x or die "Invalid prerequisite condition '$_' for $modname";$version=$self->perl_version_to_float($version)if$modname eq 'perl';next if$op eq '>=' and!$version;unless ($self->compare_versions($status{have},$op,$version)){$status{message}="$modname ($status{have}) is installed, but we need version $op $version";return \%status}}$status{ok}=1;return \%status}sub compare_versions {my$self=shift;my ($v1,$op,$v2)=@_;$v1=version->new($v1)unless eval {$v1->isa('version')};my$eval_str="\$v1 $op \$v2";my$result=eval$eval_str;$self->log_warn("error comparing versions: '$eval_str' $@")if $@;return$result}sub check_installed_version {my ($self,$modname,$spec)=@_;my$status=$self->check_installed_status($modname,$spec);if ($status->{ok}){return$status->{have}if$status->{have}and "$status->{have}" ne '<none>';return '0 but true'}$@=$status->{message};return 0}sub make_executable {my$self=shift;for (@_){my$current_mode=(stat $_)[2];chmod$current_mode | oct(111),$_}}sub is_executable {my ($self,$file)=@_;return -x $file}sub _startperl {shift()->config('startperl')}sub _added_to_INC {my$self=shift;my%seen;$seen{$_}++ foreach$self->_default_INC;return grep!$seen{$_}++,@INC}{my@default_inc;sub _default_INC {my$self=shift;return@default_inc if@default_inc;local$ENV{PERL5LIB};my$perl=ref($self)? $self->perl : $self->find_perl_interpreter;my@inc=$self->_backticks($perl,'-le','print for @INC');chomp@inc;return@default_inc=@inc}}sub print_build_script {my ($self,$fh)=@_;my$build_package=$self->build_class;my$closedata="";my$config_requires;if (-f $self->metafile){my$meta=eval {$self->read_metafile($self->metafile)};$config_requires=$meta && $meta->{prereqs}{configure}{requires}{'Module::Build'}}$config_requires ||= 0;my%q=map {$_,$self->$_()}qw(config_dir base_dir);$q{base_dir}=Win32::GetShortPathName($q{base_dir})if$self->is_windowsish;$q{magic_numfile}=$self->config_file('magicnum');my@myINC=$self->_added_to_INC;for (@myINC,values%q){$_=File::Spec->canonpath($_)unless$self->is_vmsish;s/([\\\'])/\\$1/g}my$quoted_INC=join ",\n",map " '$_'",@myINC;my$shebang=$self->_startperl;my$magic_number=$self->magic_number;my$dot_in_inc_code=$INC[-1]eq '.' ? <<'END' : '';print$fh <<EOF}sub create_mymeta {my ($self)=@_;my ($meta_obj,$mymeta);my@metafiles=($self->metafile2,$self->metafile,);my@mymetafiles=($self->mymetafile2,$self->mymetafile,);for my$f (@mymetafiles){if ($self->delete_filetree($f)){$self->log_verbose("Removed previous '$f'\n")}}if ($self->try_require("CPAN::Meta","2.142060")){for my$file (@metafiles){next unless -f $file;$meta_obj=eval {CPAN::Meta->load_file($file,{lazy_validation=>0 })};last if$meta_obj}}my$mymeta_obj;if ($meta_obj){my%updated=(%{$meta_obj->as_struct({version=>2.0 })},prereqs=>$self->_normalize_prereqs,dynamic_config=>0,generated_by=>"Module::Build version $Module::Build::VERSION",);$mymeta_obj=CPAN::Meta->new(\%updated,{lazy_validation=>0 })}else {$mymeta_obj=$self->_get_meta_object(quiet=>0,dynamic=>0,fatal=>1,auto=>0)}my@created=$self->_write_meta_files($mymeta_obj,'MYMETA');$self->log_warn("Could not create MYMETA files\n")unless@created;return 1}sub create_build_script {my ($self)=@_;$self->write_config;$self->create_mymeta;my ($build_script,$dist_name,$dist_version)=map$self->$_(),qw(build_script dist_name dist_version);if ($self->delete_filetree($build_script)){$self->log_verbose("Removed previous script '$build_script'\n")}$self->log_info("Creating new '$build_script' script for ","'$dist_name' version '$dist_version'\n");open(my$fh,'>',$build_script)or die "Can't create '$build_script': $!";$self->print_build_script($fh);close$fh;$self->make_executable($build_script);return 1}sub check_manifest {my$self=shift;return unless -e 'MANIFEST';require ExtUtils::Manifest;local ($^W,$ExtUtils::Manifest::Quiet)=(0,1);$self->log_verbose("Checking whether your kit is complete...\n");if (my@missed=ExtUtils::Manifest::manicheck()){$self->log_warn("WARNING: the following files are missing in your kit:\n","\t",join("\n\t",@missed),"\n","Please inform the author.\n\n")}else {$self->log_verbose("Looks good\n\n")}}sub dispatch {my$self=shift;local$self->{_completed_actions}={};if (@_){my ($action,%p)=@_;my$args=$p{args}? delete($p{args}): {};local$self->{invoked_action}=$action;local$self->{args}={%{$self->{args}},%$args};local$self->{properties}={%{$self->{properties}},%p};return$self->_call_action($action)}die "No build action specified" unless$self->{action};local$self->{invoked_action}=$self->{action};$self->_call_action($self->{action})}sub _call_action {my ($self,$action)=@_;return if$self->{_completed_actions}{$action}++;local$self->{action}=$action;my$method=$self->can_action($action);die "No action '$action' defined, try running the 'help' action.\n" unless$method;$self->log_debug("Starting ACTION_$action\n");my$rc=$self->$method();$self->log_debug("Finished ACTION_$action\n");return$rc}sub can_action {my ($self,$action)=@_;return$self->can("ACTION_$action")}sub cull_options {my$self=shift;my (@argv)=@_;return({},@argv)unless(ref($self));my$specs=$self->get_options;return({},@argv)unless($specs and %$specs);require Getopt::Long;my@specs;my$args={};for my$k (sort keys %$specs){my$v=$specs->{$k};die "Option specification '$k' conflicts with a " .ref$self ." option of the same name" if$self->valid_property($k);push@specs,$k .(defined$v->{type}? $v->{type}: '');push@specs,$v->{store}if exists$v->{store};$args->{$k}=$v->{default}if exists$v->{default}}local@ARGV=@argv;if (@specs){Getopt::Long::Configure('pass_through');Getopt::Long::GetOptions($args,@specs)}return$args,@ARGV}sub unparse_args {my ($self,$args)=@_;my@out;for my$k (sort keys %$args){my$v=$args->{$k};push@out,(ref$v eq 'HASH' ? map {+"--$k","$_=$v->{$_}"}sort keys %$v : ref$v eq 'ARRAY' ? map {+"--$k",$_}@$v : ("--$k",$v))}return@out}sub args {my$self=shift;return wantarray ? %{$self->{args}}: $self->{args}unless @_;my$key=shift;$self->{args}{$key}=shift if @_;return$self->{args}{$key}}sub _translate_option {my$self=shift;my$opt=shift;(my$tr_opt=$opt)=~ tr/-/_/;return$tr_opt if grep$tr_opt =~ /^(?:no_?)?$_$/,qw(create_license create_makefile_pl create_readme extra_compiler_flags extra_linker_flags install_base install_path meta_add meta_merge test_files use_rcfile use_tap_harness tap_harness_args cpan_client pureperl_only allow_pureperl);return$opt}my%singular_argument=map {($_=>1)}qw/install_base prefix destdir installdirs verbose quiet uninst debug sign/;sub _read_arg {my ($self,$args,$key,$val)=@_;$key=$self->_translate_option($key);if (exists$args->{$key}and not $singular_argument{$key}){$args->{$key}=[$args->{$key}]unless ref$args->{$key};push @{$args->{$key}},$val}else {$args->{$key}=$val}}sub _optional_arg {my$self=shift;my$opt=shift;my$argv=shift;$opt=$self->_translate_option($opt);my@bool_opts=qw(build_bat create_license create_readme pollute quiet uninst use_rcfile verbose debug sign use_tap_harness pureperl_only allow_pureperl);if (grep$opt =~ /^no[-_]?$_$/,@bool_opts){$opt =~ s/^no-?//;return ($opt,0)}return ($opt,shift(@$argv))unless grep $_ eq $opt,@bool_opts;my$arg=1;$arg=shift(@$argv)if @$argv && $argv->[0]=~ /^\d+$/;return ($opt,$arg)}sub read_args {my$self=shift;(my$args,@_)=$self->cull_options(@_);my%args=%$args;my$opt_re=qr/[\w\-]+/;my ($action,@argv);while (@_){local $_=shift;if (/^(?:--)?($opt_re)=(.*)$/){$self->_read_arg(\%args,$1,$2)}elsif (/^--($opt_re)$/){my($opt,$arg)=$self->_optional_arg($1,\@_);$self->_read_arg(\%args,$opt,$arg)}elsif (/^($opt_re)$/ and!defined($action)){$action=$1}else {push@argv,$_}}$args{ARGV}=\@argv;for ('extra_compiler_flags','extra_linker_flags'){$args{$_}=[$self->split_like_shell($args{$_})]if exists$args{$_}}for ('include_dirs'){$args{$_}=[$args{$_}]if exists$args{$_}&&!ref$args{$_}}for ($self->hash_properties,'config'){next unless exists$args{$_};my%hash;$args{$_}||= [];$args{$_}=[$args{$_}]unless ref$args{$_};for my$arg (@{$args{$_}}){$arg =~ /($opt_re)=(.*)/ or die "Malformed '$_' argument: '$arg' should be something like 'foo=bar'";$hash{$1}=$2}$args{$_}=\%hash}for my$key (qw(prefix install_base destdir)){next if!defined$args{$key};$args{$key}=$self->_detildefy($args{$key})}for my$key (qw(install_path)){next if!defined$args{$key};for my$subkey (keys %{$args{$key}}){next if!defined$args{$key}{$subkey};my$subkey_ext=$self->_detildefy($args{$key}{$subkey});if ($subkey eq 'html'){$args{$key}{binhtml}=$subkey_ext;$args{$key}{libhtml}=$subkey_ext}else {$args{$key}{$subkey}=$subkey_ext}}}if ($args{makefile_env_macros}){require Module::Build::Compat;%args=(%args,Module::Build::Compat->makefile_to_build_macros)}return \%args,$action}sub _detildefy {}sub _merge_arglist {my($self,$opts1,$opts2)=@_;$opts1 ||= {};$opts2 ||= {};my%new_opts=%$opts1;while (my ($key,$val)=each %$opts2){if (exists($opts1->{$key})){if (ref($val)eq 'HASH'){while (my ($k,$v)=each %$val){$new_opts{$key}{$k}=$v unless exists($opts1->{$key}{$k})}}}else {$new_opts{$key}=$val}}return%new_opts}sub _home_dir {my@home_dirs;push(@home_dirs,$ENV{HOME})if$ENV{HOME};push(@home_dirs,File::Spec->catpath($ENV{HOMEDRIVE},$ENV{HOMEPATH},''))if$ENV{HOMEDRIVE}&& $ENV{HOMEPATH};my@other_home_envs=qw(USERPROFILE APPDATA WINDIR SYS$LOGIN);push(@home_dirs,map$ENV{$_},grep$ENV{$_},@other_home_envs);my@real_home_dirs=grep -d,@home_dirs;return wantarray ? @real_home_dirs : shift(@real_home_dirs)}sub _find_user_config {my$self=shift;my$file=shift;for my$dir ($self->_home_dir){my$path=File::Spec->catfile($dir,$file);return$path if -e $path}return undef}sub read_modulebuildrc {my($self,$action)=@_;return ()unless$self->use_rcfile;my$modulebuildrc;if (exists($ENV{MODULEBUILDRC})&& $ENV{MODULEBUILDRC}eq 'NONE'){return ()}elsif (exists($ENV{MODULEBUILDRC})&& -e $ENV{MODULEBUILDRC}){$modulebuildrc=$ENV{MODULEBUILDRC}}elsif (exists($ENV{MODULEBUILDRC})){$self->log_warn("WARNING: Can't find resource file " ."'$ENV{MODULEBUILDRC}' defined in environment.\n" ."No options loaded\n");return ()}else {$modulebuildrc=$self->_find_user_config('.modulebuildrc');return ()unless$modulebuildrc}open(my$fh,'<',$modulebuildrc)or die "Can't open $modulebuildrc: $!";my%options;my$buffer='';while (defined(my$line=<$fh>)){chomp($line);$line =~ s/#.*$//;next unless length($line);if ($line =~ /^\S/){if ($buffer){my($action,$options)=split(/\s+/,$buffer,2);$options{$action}.= $options .' ';$buffer=''}$buffer=$line}else {$buffer .= $line}}if ($buffer){my($action,$options)=split(/\s+/,$buffer,2);$options{$action}.= $options .' '}my ($global_opts)=$self->read_args($self->split_like_shell($options{'*'}|| ''));if ($action eq 'fakeinstall' &&!exists$options{fakeinstall}){$action='install'}my ($action_opts)=$self->read_args($self->split_like_shell($options{$action}|| ''));return$self->_merge_arglist($action_opts,$global_opts)}sub merge_modulebuildrc {my($self,$action,%cmdline_opts)=@_;my%rc_opts=$self->read_modulebuildrc($action || $self->{action}|| 'build');my%new_opts=$self->_merge_arglist(\%cmdline_opts,\%rc_opts);$self->merge_args($action,%new_opts)}sub merge_args {my ($self,$action,%args)=@_;$self->{action}=$action if defined$action;my%additive=map {$_=>1}$self->hash_properties;while (my ($key,$val)=each%args){$self->{phash}{runtime_params}->access($key=>$val)if$self->valid_property($key);if ($key eq 'config'){$self->config($_=>$val->{$_})foreach keys %$val}else {my$add_to=$additive{$key}? $self->{properties}{$key}: $self->valid_property($key)? $self->{properties}: $self->{args};if ($additive{$key}){$add_to->{$_}=$val->{$_}foreach keys %$val}else {$add_to->{$key}=$val}}}}sub cull_args {my$self=shift;my@arg_list=@_;unshift@arg_list,$self->split_like_shell($ENV{PERL_MB_OPT})if$ENV{PERL_MB_OPT};my ($args,$action)=$self->read_args(@arg_list);$self->merge_args($action,%$args);$self->merge_modulebuildrc($action,%$args)}sub super_classes {my ($self,$class,$seen)=@_;$class ||= ref($self)|| $self;$seen ||= {};no strict 'refs';my@super=grep {not $seen->{$_}++}$class,@{$class .'::ISA'};return@super,map {$self->super_classes($_,$seen)}@super}sub known_actions {my ($self)=@_;my%actions;no strict 'refs';for my$class ($self->super_classes){for (keys %{$class .'::'}){$actions{$1}++ if /^ACTION_(\w+)/}}return wantarray ? sort keys%actions : \%actions}sub get_action_docs {my ($self,$action)=@_;my$actions=$self->known_actions;die "No known action '$action'" unless$actions->{$action};my ($files_found,@docs)=(0);for my$class ($self->super_classes){(my$file=$class)=~ s{::}{/}g;$file=$INC{$file .'.pm'}or next;open(my$fh,'<',$file)or next;$files_found++;local $_;while (<$fh>){last if /^=head1 ACTIONS\s/}my$style;while (<$fh>){last if /^=head1 /;if(/^=(item|head2)\s+\Q$action\E\b/){$style=$1;push@docs,$_;last}}$style or next;if($style eq 'item'){my ($found,$inlist)=(0,0);while (<$fh>){if (/^=(item|back)/){last unless$inlist}push@docs,$_;++$inlist if /^=over/;--$inlist if /^=back/}}else {while (<$fh>){last if(/^=(?:head[12]|cut)/);push@docs,$_}}}unless ($files_found){$@="Couldn't find any documentation to search";return}unless (@docs){$@="Couldn't find any docs for action '$action'";return}return join '',@docs}sub ACTION_prereq_report {my$self=shift;$self->log_info($self->prereq_report)}sub ACTION_prereq_data {my$self=shift;$self->log_info(Module::Build::Dumper->_data_dump($self->prereq_data))}sub prereq_data {my$self=shift;my@types=('configure_requires',@{$self->prereq_action_types});my$info={map {$_=>$self->$_()}grep {%{$self->$_()}}@types };return$info}sub prereq_report {my$self=shift;my$info=$self->prereq_data;my$output='';for my$type (sort keys %$info){my$prereqs=$info->{$type};$output .= "\n$type:\n";my$mod_len=2;my$ver_len=4;my%mods;for my$modname (sort keys %$prereqs){my$spec=$prereqs->{$modname};my$len=length$modname;$mod_len=$len if$len > $mod_len;$spec ||= '0';$len=length$spec;$ver_len=$len if$len > $ver_len;my$mod=$self->check_installed_status($modname,$spec);$mod->{name}=$modname;$mod->{ok}||= 0;$mod->{ok}=!$mod->{ok}if$type =~ /^(\w+_)?conflicts$/;$mods{lc$modname}=$mod}my$space=q{ } x ($mod_len - 3);my$vspace=q{ } x ($ver_len - 3);my$sline=q{-} x ($mod_len - 3);my$vline=q{-} x ($ver_len - 3);my$disposition=($type =~ /^(\w+_)?conflicts$/)? 'Clash' : 'Need';$output .= " Module $space $disposition $vspace Have\n"." ------$sline+------$vline-+----------\n";for my$k (sort keys%mods){my$mod=$mods{$k};my$space=q{ } x ($mod_len - length$k);my$vspace=q{ } x ($ver_len - length$mod->{need});my$f=$mod->{ok}? ' ' : '!';$output .= " $f $mod->{name} $space $mod->{need} $vspace ".(defined($mod->{have})? $mod->{have}: "")."\n"}}return$output}sub ACTION_help {my ($self)=@_;my$actions=$self->known_actions;if (@{$self->{args}{ARGV}}){my$msg=eval {$self->get_action_docs($self->{args}{ARGV}[0],$actions)};print $@ ? "$@\n" : $msg;return}print <<EOF;print$self->_action_listing($actions);print "\nRun `Build help <action>` for details on an individual action.\n";print "See `perldoc Module::Build` for complete documentation.\n"}sub _action_listing {my ($self,$actions)=@_;my@actions=sort keys %$actions;@actions=map$actions[($_ + ($_ % 2)* @actions)/ 2],0..$#actions;my$out='';while (my ($one,$two)=splice@actions,0,2){$out .= sprintf(" %-12s %-12s\n",$one,$two||'')}$out =~ s{\s*$}{}mg;return$out}sub ACTION_retest {my ($self)=@_;local@INC=@INC;@INC=grep {ref()|| -d}@INC if@INC > 100;$self->do_tests}sub ACTION_testall {my ($self)=@_;my@types;for my$action (grep {$_ ne 'all'}$self->get_test_types){push(@types,$action)}$self->generic_test(types=>['default',@types])}sub get_test_types {my ($self)=@_;my$t=$self->{properties}->{test_types};return (defined$t ? (wantarray ? sort keys %$t : keys %$t): ())}sub ACTION_test {my ($self)=@_;$self->generic_test(type=>'default')}sub generic_test {my$self=shift;(@_ % 2)and croak('Odd number of elements in argument hash');my%args=@_;my$p=$self->{properties};my@types=((exists($args{type})? $args{type}: ()),(exists($args{types})? @{$args{types}}: ()),);@types or croak "need some types of tests to check";my%test_types=(default=>$p->{test_file_exts},(defined($p->{test_types})? %{$p->{test_types}}: ()),);for my$type (@types){croak "$type not defined in test_types!" unless defined$test_types{$type }}local$p->{test_file_exts}=[map {ref $_ ? @$_ : $_}@test_types{@types}];$self->depends_on('code');local@INC=@INC;unshift@INC,(File::Spec->catdir($p->{base_dir},$self->blib,'lib'),File::Spec->catdir($p->{base_dir},$self->blib,'arch'));@INC=grep {ref()|| -d}@INC if@INC > 100;$self->do_tests}sub do_tests {my$self=shift;my$tests=$self->find_test_files;local$ENV{PERL_DL_NONLAZY}=1;if(@$tests){my$args=$self->tap_harness_args;if($self->use_tap_harness or ($args and %$args)){my$aggregate=$self->run_tap_harness($tests);if ($aggregate->has_errors){die "Errors in testing. Cannot continue.\n"}}else {$self->run_test_harness($tests)}}else {$self->log_info("No tests defined.\n")}$self->run_visual_script}sub run_tap_harness {my ($self,$tests)=@_;require TAP::Harness::Env;my$aggregate=TAP::Harness::Env->create({lib=>[@INC],verbosity=>$self->{properties}{verbose},switches=>[$self->harness_switches ],%{$self->tap_harness_args},})->runtests(@$tests);return$aggregate}sub run_test_harness {my ($self,$tests)=@_;require Test::Harness;local$Test::Harness::verbose=$self->verbose || 0;local$Test::Harness::switches=join ' ',$self->harness_switches;Test::Harness::runtests(@$tests)}sub run_visual_script {my$self=shift;$self->run_perl_script('visual.pl','-Mblib='.$self->blib)if -e 'visual.pl'}sub harness_switches {my$self=shift;my@res;push@res,qw(-w -d) if$self->{properties}{debugger};push@res,'-MDevel::Cover' if$self->{properties}{cover};return@res}sub test_files {my$self=shift;my$p=$self->{properties};if (@_){return$p->{test_files}=(@_==1 ? shift : [@_])}return$self->find_test_files}sub expand_test_dir {my ($self,$dir)=@_;my$exts=$self->{properties}{test_file_exts};return sort map {@{$self->rscan_dir($dir,qr{^[^.].*\Q$_\E$})}}@$exts if$self->recursive_test_files;return sort map {glob File::Spec->catfile($dir,"*$_")}@$exts}sub ACTION_testdb {my ($self)=@_;local$self->{properties}{debugger}=1;$self->depends_on('test')}sub ACTION_testcover {my ($self)=@_;unless (Module::Metadata->find_module_by_name('Devel::Cover')){warn("Cannot run testcover action unless Devel::Cover is installed.\n");return}$self->add_to_cleanup('coverage','cover_db');$self->depends_on('code');if (-e 'cover_db'){my$pm_files=$self->rscan_dir (File::Spec->catdir($self->blib,'lib'),$self->file_qr('\.pm$'));my$cover_files=$self->rscan_dir('cover_db',sub {-f $_ and not /\.html$/});$self->do_system(qw(cover -delete))unless$self->up_to_date($pm_files,$cover_files)&& $self->up_to_date($self->test_files,$cover_files)}local$self->{properties}{cover}=1;$self->depends_on('test');$self->do_system('cover')}sub ACTION_code {my ($self)=@_;my$blib=$self->blib;$self->add_to_cleanup($blib);File::Path::mkpath(File::Spec->catdir($blib,'arch'));if (my$split=$self->autosplit){$self->autosplit_file($_,$blib)for ref($split)? @$split : ($split)}for my$element (@{$self->build_elements}){my$method="process_${element}_files";$method="process_files_by_extension" unless$self->can($method);$self->$method($element)}$self->depends_on('config_data')}sub ACTION_build {my$self=shift;$self->log_info("Building " .$self->dist_name ."\n");$self->depends_on('code');$self->depends_on('docs')}sub process_files_by_extension {my ($self,$ext)=@_;my$method="find_${ext}_files";my$files=$self->can($method)? $self->$method(): $self->_find_file_by_type($ext,'lib');for my$file (sort keys %$files){$self->copy_if_modified(from=>$file,to=>File::Spec->catfile($self->blib,$files->{$file}))}}sub process_support_files {my$self=shift;my$p=$self->{properties};return unless$p->{c_source};my$files;if (ref($p->{c_source})eq "ARRAY"){push @{$p->{include_dirs}},@{$p->{c_source}};for my$path (@{$p->{c_source}}){push @$files,@{$self->rscan_dir($path,$self->file_qr('\.c(c|p|pp|xx|\+\+)?$'))}}}else {push @{$p->{include_dirs}},$p->{c_source};$files=$self->rscan_dir($p->{c_source},$self->file_qr('\.c(c|p|pp|xx|\+\+)?$'))}for my$file (@$files){push @{$p->{objects}},$self->compile_c($file)}}sub process_share_dir_files {my$self=shift;my$files=$self->_find_share_dir_files;return unless$files;my$share_prefix=File::Spec->catdir($self->blib,qw/lib auto share/);for my$file (sort keys %$files){$self->copy_if_modified(from=>$file,to=>File::Spec->catfile($share_prefix,$files->{$file}))}}sub _find_share_dir_files {my$self=shift;my$share_dir=$self->share_dir;return unless$share_dir;my@file_map;if ($share_dir->{dist}){my$prefix="dist/".$self->dist_name;push@file_map,$self->_share_dir_map($prefix,$share_dir->{dist})}if ($share_dir->{module}){for my$mod (sort keys %{$share_dir->{module}}){(my$altmod=$mod)=~ s{::}{-}g;my$prefix="module/$altmod";push@file_map,$self->_share_dir_map($prefix,$share_dir->{module}{$mod})}}return {@file_map }}sub _share_dir_map {my ($self,$prefix,$list)=@_;my%files;for my$dir (@$list){for my$f (@{$self->rscan_dir($dir,sub {-f})}){$f =~ s{\A.*?\Q$dir\E/}{};$files{"$dir/$f"}="$prefix/$f"}}return%files}sub process_PL_files {my ($self)=@_;my$files=$self->find_PL_files;for my$file (sort keys %$files){my$to=$files->{$file};unless ($self->up_to_date($file,$to)){$self->run_perl_script($file,[],[@$to])or die "$file failed";$self->add_to_cleanup(@$to)}}}sub process_xs_files {my$self=shift;return if$self->pureperl_only && $self->allow_pureperl;my$files=$self->find_xs_files;croak 'Can\'t build xs files under --pureperl-only' if %$files && $self->pureperl_only;for my$from (sort keys %$files){my$to=$files->{$from};unless ($from eq $to){$self->add_to_cleanup($to);$self->copy_if_modified(from=>$from,to=>$to)}$self->process_xs($to)}}sub process_pod_files {shift()->process_files_by_extension(shift())}sub process_pm_files {shift()->process_files_by_extension(shift())}sub process_script_files {my$self=shift;my$files=$self->find_script_files;return unless keys %$files;my$script_dir=File::Spec->catdir($self->blib,'script');File::Path::mkpath($script_dir);for my$file (sort keys %$files){my$result=$self->copy_if_modified($file,$script_dir,'flatten')or next;$self->fix_shebang_line($result)unless$self->is_vmsish;$self->make_executable($result)}}sub find_PL_files {my$self=shift;if (my$files=$self->{properties}{PL_files}){if (ref$files eq 'ARRAY'){return {map {$_,[/^(.*)\.PL$/]}map$self->localize_file_path($_),@$files }}elsif (ref$files eq 'HASH'){my%out;while (my ($file,$to)=each %$files){$out{$self->localize_file_path($file)}=[map$self->localize_file_path($_),ref$to ? @$to : ($to)]}return \%out}else {die "'PL_files' must be a hash reference or array reference"}}return unless -d 'lib';return {map {$_,[/^(.*)\.PL$/i ]}@{$self->rscan_dir('lib',$self->file_qr('\.PL$'))}}}sub find_pm_files {shift->_find_file_by_type('pm','lib')}sub find_pod_files {shift->_find_file_by_type('pod','lib')}sub find_xs_files {shift->_find_file_by_type('xs','lib')}sub find_script_files {my$self=shift;if (my$files=$self->script_files){return {map {$self->localize_file_path($_),$files->{$_}}keys %$files }}return {}}sub find_test_files {my$self=shift;my$p=$self->{properties};if (my$files=$p->{test_files}){$files=[sort keys %$files]if ref$files eq 'HASH';$files=[map {-d $_ ? $self->expand_test_dir($_): $_}map glob,$self->split_like_shell($files)];return [map$self->localize_file_path($_),@$files ]}else {my@tests;push@tests,'test.pl' if -e 'test.pl';push@tests,$self->expand_test_dir('t')if -e 't' and -d _;return \@tests}}sub _find_file_by_type {my ($self,$type,$dir)=@_;if (my$files=$self->{properties}{"${type}_files"}){return {map$self->localize_file_path($_),%$files }}return {}unless -d $dir;return {map {$_,$_}map$self->localize_file_path($_),grep!/\.\#/,@{$self->rscan_dir($dir,$self->file_qr("\\.$type\$"))}}}sub localize_file_path {my ($self,$path)=@_;return File::Spec->catfile(split m{/},$path)}sub localize_dir_path {my ($self,$path)=@_;return File::Spec->catdir(split m{/},$path)}sub fix_shebang_line {my ($self,@files)=@_;my$c=ref($self)? $self->{config}: 'Module::Build::Config';my ($does_shbang)=$c->get('sharpbang')=~ /^\s*\#\!/;for my$file (@files){open(my$FIXIN,'<',$file)or die "Can't process '$file': $!";local $/="\n";chomp(my$line=<$FIXIN>);next unless$line =~ s/^\s*\#!\s*//;my ($cmd,$arg)=(split(' ',$line,2),'');next unless$cmd =~ /perl/i;my$interpreter=$self->{properties}{perl};$self->log_verbose("Changing sharpbang in $file to $interpreter\n");my$shb='';$shb .= $c->get('sharpbang')."$interpreter $arg\n" if$does_shbang;open(my$FIXOUT,'>',"$file.new")or die "Can't create new $file: $!\n";local $\;undef $/;print$FIXOUT $shb,<$FIXIN>;close$FIXIN;close$FIXOUT;rename($file,"$file.bak")or die "Can't rename $file to $file.bak: $!";rename("$file.new",$file)or die "Can't rename $file.new to $file: $!";$self->delete_filetree("$file.bak")or $self->log_warn("Couldn't clean up $file.bak, leaving it there");$self->do_system($c->get('eunicefix'),$file)if$c->get('eunicefix')ne ':'}}sub ACTION_testpod {my$self=shift;$self->depends_on('docs');eval q{use Test::Pod 0.95; 1} or die "The 'testpod' action requires Test::Pod version 0.95";my@files=sort keys %{$self->_find_pods($self->libdoc_dirs)},keys %{$self->_find_pods ($self->bindoc_dirs,exclude=>[$self->file_qr('\.bat$')])}or die "Couldn't find any POD files to test\n";{package Module::Build::PodTester;Test::Pod->import(tests=>scalar@files);pod_file_ok($_)foreach@files}}sub ACTION_testpodcoverage {my$self=shift;$self->depends_on('docs');eval q{use Test::Pod::Coverage 1.00; 1} or die "The 'testpodcoverage' action requires ","Test::Pod::Coverage version 1.00";local@INC=@INC;my$p=$self->{properties};unshift(@INC,File::Spec->catdir($p->{base_dir},$self->blib,'lib'),);all_pod_coverage_ok()}sub ACTION_docs {my$self=shift;$self->depends_on('code');$self->depends_on('manpages','html')}sub _is_default_installable {my$self=shift;my$type=shift;return ($self->install_destination($type)&& ($self->install_path($type)|| $self->install_sets($self->installdirs)->{$type}))? 1 : 0}sub _is_ActivePerl {my$self=shift;unless (exists($self->{_is_ActivePerl})){$self->{_is_ActivePerl}=(eval {require ActivePerl::DocTools}|| 0)}return$self->{_is_ActivePerl}}sub _is_ActivePPM {my$self=shift;unless (exists($self->{_is_ActivePPM})){$self->{_is_ActivePPM}=(eval {require ActivePerl::PPM}|| 0)}return$self->{_is_ActivePPM}}sub ACTION_manpages {my$self=shift;return unless$self->_mb_feature('manpage_support');$self->depends_on('code');my%extra_manify_args=$self->{properties}{'extra_manify_args'}? %{$self->{properties}{'extra_manify_args'}}: ();for my$type (qw(bin lib)){next unless ($self->invoked_action eq 'manpages' || $self->_is_default_installable("${type}doc"));my$files=$self->_find_pods($self->{properties}{"${type}doc_dirs"},exclude=>[$self->file_qr('\.bat$')]);next unless %$files;my$sub=$self->can("manify_${type}_pods");$self->$sub(%extra_manify_args)if defined($sub)}}sub manify_bin_pods {my$self=shift;my%podman_args=(section=>1,@_);my$files=$self->_find_pods($self->{properties}{bindoc_dirs},exclude=>[$self->file_qr('\.bat$')]);return unless keys %$files;my$mandir=File::Spec->catdir($self->blib,'bindoc');File::Path::mkpath($mandir,0,oct(777));require Pod::Man;for my$file (sort keys %$files){my$parser=Pod::Man->new(%podman_args);my$manpage=$self->man1page_name($file).'.' .$self->config('man1ext');my$outfile=File::Spec->catfile($mandir,$manpage);next if$self->up_to_date($file,$outfile);$self->log_verbose("Manifying $file -> $outfile\n");eval {$parser->parse_from_file($file,$outfile);1}or $self->log_warn("Error creating '$outfile': $@\n");$files->{$file}=$outfile}}sub manify_lib_pods {my$self=shift;my%podman_args=(section=>3,@_);my$files=$self->_find_pods($self->{properties}{libdoc_dirs});return unless keys %$files;my$mandir=File::Spec->catdir($self->blib,'libdoc');File::Path::mkpath($mandir,0,oct(777));require Pod::Man;for my$file (sort keys %$files){my$parser=Pod::Man->new(%podman_args);my$manpage=$self->man3page_name($files->{$file}).'.' .$self->config('man3ext');my$outfile=File::Spec->catfile($mandir,$manpage);next if$self->up_to_date($file,$outfile);$self->log_verbose("Manifying $file -> $outfile\n");eval {$parser->parse_from_file($file,$outfile);1}or $self->log_warn("Error creating '$outfile': $@\n");$files->{$file}=$outfile}}sub _find_pods {my ($self,$dirs,%args)=@_;my%files;for my$spec (@$dirs){my$dir=$self->localize_dir_path($spec);next unless -e $dir;FILE: foreach my$file (@{$self->rscan_dir($dir)}){for my$regexp (@{$args{exclude}}){next FILE if$file =~ $regexp}$file=$self->localize_file_path($file);$files{$file}=File::Spec->abs2rel($file,$dir)if$self->contains_pod($file)}}return \%files}sub contains_pod {my ($self,$file)=@_;return '' unless -T $file;open(my$fh,'<',$file)or die "Can't open $file: $!";while (my$line=<$fh>){return 1 if$line =~ /^\=(?:head|pod|item)/}return ''}sub ACTION_html {my$self=shift;return unless$self->_mb_feature('HTML_support');$self->depends_on('code');for my$type (qw(bin lib)){next unless ($self->invoked_action eq 'html' || $self->_is_default_installable("${type}html"));$self->htmlify_pods($type)}}sub htmlify_pods {my$self=shift;my$type=shift;my$htmldir=shift || File::Spec->catdir($self->blib,"${type}html");$self->add_to_cleanup('pod2htm*');my$pods=$self->_find_pods($self->{properties}{"${type}doc_dirs"},exclude=>[$self->file_qr('\.(?:bat|com|html)$')]);return unless %$pods;unless (-d $htmldir){File::Path::mkpath($htmldir,0,oct(755))or die "Couldn't mkdir $htmldir: $!"}my@rootdirs=($type eq 'bin')? qw(bin) : $self->installdirs eq 'core' ? qw(lib) : qw(site lib);my$podroot=$ENV{PERL_CORE}? File::Basename::dirname($ENV{PERL_CORE}): $self->original_prefix('core');my$htmlroot=$self->install_sets('core')->{libhtml};my$podpath;unless (defined$self->args('html_links')and!$self->args('html_links')){my@podpath=((map {File::Spec->abs2rel($_,$podroot)}grep {-d}($self->install_sets('core','lib'),$self->install_sets('core','bin'),$self->install_sets('site','lib'),)),File::Spec->rel2abs($self->blib));$podpath=$ENV{PERL_CORE}? File::Spec->catdir($podroot,'lib'): join(":",map {tr,:\\,|/,;$_}@podpath)}my$blibdir=join('/',File::Spec->splitdir((File::Spec->splitpath(File::Spec->rel2abs($htmldir),1))[1]),'');my ($with_ActiveState,$htmltool);if ($with_ActiveState=$self->_is_ActivePerl && eval {require ActivePerl::DocTools::Pod;1}){my$tool_v=ActiveState::DocTools::Pod->VERSION;$htmltool="ActiveState::DocTools::Pod";$htmltool .= " $tool_v" if$tool_v && length$tool_v}else {require Module::Build::PodParser;require Pod::Html;$htmltool="Pod::Html " .Pod::Html->VERSION}$self->log_verbose("Converting Pod to HTML with $htmltool\n");my$errors=0;POD: foreach my$pod (sort keys %$pods){my ($name,$path)=File::Basename::fileparse($pods->{$pod},$self->file_qr('\.(?:pm|plx?|pod)$'));my@dirs=File::Spec->splitdir(File::Spec->canonpath($path));pop(@dirs)if scalar(@dirs)&& $dirs[-1]eq File::Spec->curdir;my$fulldir=File::Spec->catdir($htmldir,@rootdirs,@dirs);my$tmpfile=File::Spec->catfile($fulldir,"${name}.tmp");my$outfile=File::Spec->catfile($fulldir,"${name}.html");my$infile=File::Spec->abs2rel($pod);next if$self->up_to_date($infile,$outfile);unless (-d $fulldir){File::Path::mkpath($fulldir,0,oct(755))or die "Couldn't mkdir $fulldir: $!"}$self->log_verbose("HTMLifying $infile -> $outfile\n");if ($with_ActiveState){my$depth=@rootdirs + @dirs;my%opts=(infile=>$infile,outfile=>$tmpfile,(defined($podpath)? (podpath=>$podpath): ()),podroot=>$podroot,index=>1,depth=>$depth,);eval {ActivePerl::DocTools::Pod::pod2html(map {($_,$opts{$_})}sort keys%opts);1}or $self->log_warn("[$htmltool] pod2html (" .join(", ",map {"q{$_} => q{$opts{$_}}"}(sort keys%opts)).") failed: $@")}else {my$path2root=File::Spec->catdir((File::Spec->updir)x @dirs);open(my$fh,'<',$infile)or die "Can't read $infile: $!";my$abstract=Module::Build::PodParser->new(fh=>$fh)->get_abstract();my$title=join('::',(@dirs,$name));$title .= " - $abstract" if$abstract;my@opts=("--title=$title",(defined($podpath)? "--podpath=$podpath" : ()),"--infile=$infile","--outfile=$tmpfile","--podroot=$podroot",($path2root ? "--htmlroot=$path2root" : ()),);unless (eval{Pod::Html->VERSION(1.12)}){push(@opts,('--flush'))}if (eval{Pod::Html->VERSION(1.12)}){push(@opts,('--header','--backlink'))}elsif (eval{Pod::Html->VERSION(1.03)}){push(@opts,('--header','--backlink=Back to Top'))}$self->log_verbose("P::H::pod2html @opts\n");{my$orig=Cwd::getcwd();eval {Pod::Html::pod2html(@opts);1}or $self->log_warn("[$htmltool] pod2html( " .join(", ",map {"q{$_}"}@opts).") failed: $@");chdir($orig)}}if (!-r $tmpfile){$errors++;next POD}open(my$fh,'<',$tmpfile)or die "Can't read $tmpfile: $!";my$html=join('',<$fh>);close$fh;if (!$self->_is_ActivePerl){$html =~ s#^<!DOCTYPE .*?>#<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">#im;$html =~ s#<html xmlns="http://www.w3.org/1999/xhtml">#<html>#i;$html =~ s#<head>#<head>\n<!-- saved from url=(0017)http://localhost/ -->#i}$html =~ s/\Q$blibdir\E//g;open($fh,'>',$outfile)or die "Can't write $outfile: $!";print$fh $html;close$fh;unlink($tmpfile)}return!$errors}sub man1page_name {my$self=shift;return File::Basename::basename(shift)}sub man3page_name {my$self=shift;my ($vol,$dirs,$file)=File::Spec->splitpath(shift);my@dirs=File::Spec->splitdir(File::Spec->canonpath($dirs));$file =~ s/\.p(?:od|m|l)\z//i;return join($self->manpage_separator,@dirs,$file)}sub manpage_separator {return '::'}sub ACTION_diff {my$self=shift;$self->depends_on('build');my$local_lib=File::Spec->rel2abs('lib');my@myINC=grep {$_ ne $local_lib}@INC;push@myINC,map$self->install_destination($_),qw(lib arch);my@flags=@{$self->{args}{ARGV}};@flags=$self->split_like_shell($self->{args}{flags}|| '')unless@flags;my$installmap=$self->install_map;delete$installmap->{read};delete$installmap->{write};my$text_suffix=$self->file_qr('\.(pm|pod)$');for my$localdir (sort keys %$installmap){my@localparts=File::Spec->splitdir($localdir);my$files=$self->rscan_dir($localdir,sub {-f});for my$file (@$files){my@parts=File::Spec->splitdir($file);@parts=@parts[@localparts .. $#parts];my$installed=Module::Metadata->find_module_by_name(join('::',@parts),\@myINC);if (not $installed){print "Only in lib: $file\n";next}my$status=File::Compare::compare($installed,$file);next if$status==0;die "Can't compare $installed and $file: $!" if$status==-1;if ($file =~ $text_suffix){$self->do_system('diff',@flags,$installed,$file)}else {print "Binary files $file and $installed differ\n"}}}}sub ACTION_pure_install {shift()->depends_on('install')}sub ACTION_install {my ($self)=@_;require ExtUtils::Install;$self->depends_on('build');$self->_do_in_dir(".",sub {ExtUtils::Install::install($self->install_map,$self->verbose,0,$self->{args}{uninst}||0)});if ($self->_is_ActivePerl && $self->{_completed_actions}{html}){$self->log_info("Building ActivePerl Table of Contents\n");eval {ActivePerl::DocTools::WriteTOC(verbose=>$self->verbose ? 1 : 0);1}or $self->log_warn("AP::DT:: WriteTOC() failed: $@")}if ($self->_is_ActivePPM){my$F_perllocal=File::Spec->catfile($self->install_sets('core','lib'),'perllocal.pod');my$dt_stamp=time;$self->log_info("For ActivePerl's PPM: touch '$F_perllocal'\n");open my$perllocal,">>",$F_perllocal;close$perllocal;utime($dt_stamp,$dt_stamp,$F_perllocal)}}sub ACTION_fakeinstall {my ($self)=@_;require ExtUtils::Install;my$eui_version=ExtUtils::Install->VERSION;if ($eui_version < 1.32){$self->log_warn("The 'fakeinstall' action requires Extutils::Install 1.32 or later.\n" ."(You only have version $eui_version).");return}$self->depends_on('build');ExtUtils::Install::install($self->install_map,!$self->quiet,1,$self->{args}{uninst}||0)}sub ACTION_versioninstall {my ($self)=@_;die "You must have only.pm 0.25 or greater installed for this operation: $@\n" unless eval {require only;'only'->VERSION(0.25);1};$self->depends_on('build');my%onlyargs=map {exists($self->{args}{$_})? ($_=>$self->{args}{$_}): ()}qw(version versionlib);only::install::install(%onlyargs)}sub ACTION_installdeps {my ($self)=@_;my$info=$self->_enum_prereqs;if (!$info){$self->log_info("No prerequisites detected\n");return}my$failures=$self->prereq_failures($info);if (!$failures){$self->log_info("All prerequisites satisfied\n");return}my@install;for my$type (sort keys %$failures){my$prereqs=$failures->{$type};if($type =~ m/^(?:\w+_)?requires$/){push(@install,sort keys %$prereqs);next}$self->log_info("Checking optional dependencies:\n");for my$module (sort keys %$prereqs){push(@install,$module)if($self->y_n("Install $module?",'y'))}}return unless@install;my ($command,@opts)=$self->split_like_shell($self->cpan_client);if (!File::Spec->file_name_is_absolute($command)){my@loc=('site','vendor','');my@bindirs=File::Basename::dirname($self->perl);push@bindirs,map {($self->config->{"install${_}bin"},$self->config->{"install${_}script"})}@loc;for my$d (@bindirs){my$abs_cmd=$self->find_command(File::Spec->catfile($d,$command));if (defined$abs_cmd){$command=$abs_cmd;last}}}$self->do_system($command,@opts,@install)}sub ACTION_clean {my ($self)=@_;$self->log_info("Cleaning up build files\n");for my$item (map glob($_),$self->cleanup){$self->delete_filetree($item)}}sub ACTION_realclean {my ($self)=@_;$self->depends_on('clean');$self->log_info("Cleaning up configuration files\n");$self->delete_filetree($self->config_dir,$self->mymetafile,$self->mymetafile2,$self->build_script)}sub ACTION_ppd {my ($self)=@_;require Module::Build::PPMMaker;my$ppd=Module::Build::PPMMaker->new();my$file=$ppd->make_ppd(%{$self->{args}},build=>$self);$self->add_to_cleanup($file)}sub ACTION_ppmdist {my ($self)=@_;$self->depends_on('build');my$ppm=$self->ppm_name;$self->delete_filetree($ppm);$self->log_info("Creating $ppm\n");$self->add_to_cleanup($ppm,"$ppm.tar.gz");my%types=(lib=>'lib',arch=>'arch',bin=>'bin',script=>'script',bindoc=>'man1',libdoc=>'man3',binhtml=>undef,libhtml=>undef,);for my$type ($self->install_types){next if exists($types{$type})&&!defined($types{$type});my$dir=File::Spec->catdir($self->blib,$type);next unless -e $dir;my$files=$self->rscan_dir($dir);for my$file (@$files){next unless -f $file;my$rel_file=File::Spec->abs2rel(File::Spec->rel2abs($file),File::Spec->rel2abs($dir));my$to_file=File::Spec->catfile($ppm,'blib',exists($types{$type})? $types{$type}: $type,$rel_file);$self->copy_if_modified(from=>$file,to=>$to_file)}}for my$type (qw(bin lib)){$self->htmlify_pods($type,File::Spec->catdir($ppm,'blib','html'))}my$target=File::Spec->catfile(File::Spec->updir,$ppm);$self->_do_in_dir($ppm,sub {$self->make_tarball('blib',$target)});$self->depends_on('ppd');$self->delete_filetree($ppm)}sub ACTION_pardist {my ($self)=@_;if (not eval {require PAR::Dist;PAR::Dist->VERSION(0.17)}){$self->log_warn("In order to create .par distributions, you need to\n" ."install PAR::Dist first.");return()}$self->depends_on('build');return PAR::Dist::blib_to_par(name=>$self->dist_name,version=>$self->dist_version,)}sub ACTION_dist {my ($self)=@_;$self->dispatch('distdir');my$dist_dir=$self->dist_dir;$self->make_tarball($dist_dir);$self->delete_filetree($dist_dir)}sub ACTION_distcheck {my ($self)=@_;$self->_check_manifest_skip unless$self->invoked_action eq 'distclean';require ExtUtils::Manifest;local $^W;my ($missing,$extra)=ExtUtils::Manifest::fullcheck();return unless @$missing || @$extra;my$msg="MANIFEST appears to be out of sync with the distribution\n";if ($self->invoked_action eq 'distcheck'){die$msg}else {warn$msg}}sub _check_mymeta_skip {my$self=shift;my$maniskip=shift || 'MANIFEST.SKIP';require ExtUtils::Manifest;local $^W;my$skip_factory=ExtUtils::Manifest->can('maniskip')|| ExtUtils::Manifest->can('_maniskip');my$mymetafile=$self->mymetafile;for my$file ($self->mymetafile,$self->mymetafile2){unless ($skip_factory && $skip_factory->($maniskip)->($file)){$self->log_warn("File '$maniskip' does not include '$file'. Adding it now.\n");my$safe=quotemeta($file);$self->_append_maniskip("^$safe\$",$maniskip)}}}sub _add_to_manifest {my ($self,$manifest,$lines)=@_;$lines=[$lines]unless ref$lines;my$existing_files=$self->_read_manifest($manifest);return unless defined($existing_files);@$lines=grep {!exists$existing_files->{$_}}@$lines or return;my$mode=(stat$manifest)[2];chmod($mode | oct(222),$manifest)or die "Can't make $manifest writable: $!";open(my$fh,'<',$manifest)or die "Can't read $manifest: $!";my$last_line=(<$fh>)[-1]|| "\n";my$has_newline=$last_line =~ /\n$/;close$fh;open($fh,'>>',$manifest)or die "Can't write to $manifest: $!";print$fh "\n" unless$has_newline;print$fh map "$_\n",@$lines;close$fh;chmod($mode,$manifest);$self->log_verbose(map "Added to $manifest: $_\n",@$lines)}sub _sign_dir {my ($self,$dir)=@_;unless (eval {require Module::Signature;1}){$self->log_warn("Couldn't load Module::Signature for 'distsign' action:\n $@\n");return}{my$manifest=File::Spec->catfile($dir,'MANIFEST');die "Signing a distribution requires a MANIFEST file" unless -e $manifest;$self->_add_to_manifest($manifest,"SIGNATURE Added here by Module::Build")}$self->_do_in_dir($dir,sub {local$Module::Signature::Quiet=1;Module::Signature::sign()})}sub _do_in_dir {my ($self,$dir,$do)=@_;my$start_dir=File::Spec->rel2abs($self->cwd);chdir$dir or die "Can't chdir() to $dir: $!";eval {$do->()};my@err=$@ ? ($@): ();chdir$start_dir or push@err,"Can't chdir() back to $start_dir: $!";die join "\n",@err if@err}sub ACTION_distsign {my ($self)=@_;{local$self->{properties}{sign}=0;$self->depends_on('distdir')unless -d $self->dist_dir}$self->_sign_dir($self->dist_dir)}sub ACTION_skipcheck {my ($self)=@_;require ExtUtils::Manifest;local $^W;ExtUtils::Manifest::skipcheck()}sub ACTION_distclean {my ($self)=@_;$self->depends_on('realclean');$self->depends_on('distcheck')}sub do_create_makefile_pl {my$self=shift;require Module::Build::Compat;$self->log_info("Creating Makefile.PL\n");eval {Module::Build::Compat->create_makefile_pl($self->create_makefile_pl,$self,@_)};if ($@){1 while unlink 'Makefile.PL';die "$@\n"}$self->_add_to_manifest('MANIFEST','Makefile.PL')}sub do_create_license {my$self=shift;$self->log_info("Creating LICENSE file\n");if (!$self->_mb_feature('license_creation')){$self->_warn_mb_feature_deps('license_creation');die "Aborting.\n"}my$l=$self->license or die "Can't create LICENSE file: No license specified\n";my$license=$self->_software_license_object or die << "HERE";$self->delete_filetree('LICENSE');open(my$fh,'>','LICENSE')or die "Can't write LICENSE file: $!";print$fh $license->fulltext;close$fh;$self->_add_to_manifest('MANIFEST','LICENSE')}sub do_create_readme {my$self=shift;$self->delete_filetree('README');my$docfile=$self->_main_docfile;unless ($docfile){$self->log_warn(<<EOF);return}if (eval {require Pod::Readme;Pod::Readme->can('new')}){$self->log_info("Creating README using Pod::Readme\n");my$parser=Pod::Readme->new;$parser->parse_from_file($docfile,'README',@_)}elsif (eval {require Pod::Text;1}){$self->log_info("Creating README using Pod::Text\n");if (open(my$fh,'>','README')){local $^W=0;no strict "refs";my$old_parse_file;$old_parse_file=\&{"Pod::Simple::parse_file"}and local *{"Pod::Simple::parse_file"}=sub {my$self=shift;$self->output_fh($_[1])if $_[1];$self->$old_parse_file($_[0])}if$Pod::Text::VERSION ==3.01;Pod::Text::pod2text($docfile,$fh);close$fh}else {$self->log_warn("Cannot create 'README' file: Can't open file for writing\n");return}}else {$self->log_warn("Can't load Pod::Readme or Pod::Text to create README\n");return}$self->_add_to_manifest('MANIFEST','README')}sub _main_docfile {my$self=shift;if (my$pm_file=$self->dist_version_from){(my$pod_file=$pm_file)=~ s/.pm$/.pod/;return (-e $pod_file ? $pod_file : $pm_file)}else {return undef}}sub do_create_bundle_inc {my$self=shift;my$dist_inc=File::Spec->catdir($self->dist_dir,'inc');require inc::latest;inc::latest->write($dist_inc,@{$self->bundle_inc_preload});inc::latest->bundle_module($_,$dist_inc)for @{$self->bundle_inc};return 1}sub ACTION_distdir {my ($self)=@_;if (@{$self->bundle_inc}&&!$self->_mb_feature('inc_bundling_support')){$self->_warn_mb_feature_deps('inc_bundling_support');die "Aborting.\n"}$self->depends_on('distmeta');my$dist_files=$self->_read_manifest('MANIFEST')or die "Can't create distdir without a MANIFEST file - run 'manifest' action first.\n";delete$dist_files->{SIGNATURE};die "No files found in MANIFEST - try running 'manifest' action?\n" unless ($dist_files and keys %$dist_files);my$metafile=$self->metafile;$self->log_warn("*** Did you forget to add $metafile to the MANIFEST?\n")unless exists$dist_files->{$metafile};my$dist_dir=$self->dist_dir;$self->delete_filetree($dist_dir);$self->log_info("Creating $dist_dir\n");$self->add_to_cleanup($dist_dir);for my$file (sort keys %$dist_files){next if$file =~ m{^MYMETA\.};my$new=$self->copy_if_modified(from=>$file,to_dir=>$dist_dir,verbose=>0)}$self->do_create_bundle_inc if @{$self->bundle_inc};$self->_sign_dir($dist_dir)if$self->{properties}{sign}}sub ACTION_disttest {my ($self)=@_;$self->depends_on('distdir');$self->_do_in_dir ($self->dist_dir,sub {local$ENV{AUTHOR_TESTING}=1;local$ENV{RELEASE_TESTING}=1;$self->run_perl_script('Build.PL')or die "Error executing 'Build.PL' in dist directory: $!";$self->run_perl_script($self->build_script)or die "Error executing $self->build_script in dist directory: $!";$self->run_perl_script($self->build_script,[],['test'])or die "Error executing 'Build test' in dist directory"})}sub ACTION_distinstall {my ($self,@args)=@_;$self->depends_on('distdir');$self->_do_in_dir ($self->dist_dir,sub {$self->run_perl_script('Build.PL')or die "Error executing 'Build.PL' in dist directory: $!";$self->run_perl_script($self->build_script)or die "Error executing $self->build_script in dist directory: $!";$self->run_perl_script($self->build_script,[],['install'])or die "Error executing 'Build install' in dist directory"})}sub _eumanifest_has_include {my$self=shift;require ExtUtils::Manifest;return eval {ExtUtils::Manifest->VERSION(1.50);1}}sub _default_maniskip {my$self=shift;my$default_maniskip;for my$dir (@INC){$default_maniskip=File::Spec->catfile($dir,"ExtUtils","MANIFEST.SKIP");last if -r $default_maniskip}return$default_maniskip}sub _slurp {my$self=shift;my$file=shift;my$mode=shift || "";open my$fh,"<$mode",$file or croak "Can't open $file for reading: $!";local $/;return <$fh>}sub _spew {my$self=shift;my$file=shift;my$content=shift || "";my$mode=shift || "";open my$fh,">$mode",$file or croak "Can't open $file for writing: $!";print {$fh}$content;close$fh}sub _case_tolerant {my$self=shift;if (ref$self){$self->{_case_tolerant}=File::Spec->case_tolerant unless defined($self->{_case_tolerant});return$self->{_case_tolerant}}else {return File::Spec->case_tolerant}}sub _append_maniskip {my$self=shift;my$skip=shift;my$file=shift || 'MANIFEST.SKIP';return unless defined$skip && length$skip;open(my$fh,'>>',$file)or die "Can't open $file: $!";print$fh "$skip\n";close$fh}sub _write_default_maniskip {my$self=shift;my$file=shift || 'MANIFEST.SKIP';open(my$fh,'>',$file)or die "Can't open $file: $!";my$content=$self->_eumanifest_has_include ? "#!include_default\n" : $self->_slurp($self->_default_maniskip);$content .= <<'EOF';$content .= '\b'.$self->dist_name.'-[\d\.\_]+'."\n";print$fh $content;close$fh;return}sub _check_manifest_skip {my ($self)=@_;my$maniskip='MANIFEST.SKIP';if (!-e $maniskip){$self->log_warn("File '$maniskip' does not exist: Creating a temporary '$maniskip'\n");$self->_write_default_maniskip($maniskip);$self->_unlink_on_exit($maniskip)}else {$self->_check_mymeta_skip($maniskip)}return}sub ACTION_manifest {my ($self)=@_;$self->_check_manifest_skip;require ExtUtils::Manifest;local ($^W,$ExtUtils::Manifest::Quiet)=(0,1);ExtUtils::Manifest::mkmanifest()}sub ACTION_manifest_skip {my ($self)=@_;if (-e 'MANIFEST.SKIP'){$self->log_warn("MANIFEST.SKIP already exists.\n");return 0}$self->log_info("Creating a new MANIFEST.SKIP file\n");return$self->_write_default_maniskip;return -e 'MANIFEST.SKIP'}sub file_qr {return shift->{_case_tolerant}? qr($_[0])i : qr($_[0])}sub dist_dir {my ($self)=@_;my$dir=join "-",$self->dist_name,$self->dist_version;$dir .= "-" .$self->dist_suffix if$self->dist_suffix;return$dir}sub ppm_name {my$self=shift;return 'PPM-' .$self->dist_dir}sub _files_in {my ($self,$dir)=@_;return unless -d $dir;local*DH;opendir DH,$dir or die "Can't read directory $dir: $!";my@files;while (defined (my$file=readdir DH)){my$full_path=File::Spec->catfile($dir,$file);next if -d $full_path;push@files,$full_path}return@files}sub share_dir {my$self=shift;my$p=$self->{properties};$p->{share_dir}=shift if @_;if (!defined$p->{share_dir}){return}elsif (!ref$p->{share_dir}){$p->{share_dir}={dist=>[$p->{share_dir}]}}elsif (ref$p->{share_dir}eq 'ARRAY'){$p->{share_dir}={dist=>$p->{share_dir}}}elsif (ref$p->{share_dir}eq 'HASH'){my$share_dir=$p->{share_dir};if (defined$share_dir->{dist}){if (!ref$share_dir->{dist}){$share_dir->{dist}=[$share_dir->{dist}]}elsif (ref$share_dir->{dist}ne 'ARRAY'){die "'dist' key in 'share_dir' must be scalar or arrayref"}}if (defined$share_dir->{module}){my$mod_hash=$share_dir->{module};if (ref$mod_hash eq 'HASH'){for my$k (sort keys %$mod_hash){if (!ref$mod_hash->{$k}){$mod_hash->{$k}=[$mod_hash->{$k}]}elsif(ref$mod_hash->{$k}ne 'ARRAY'){die "modules in 'module' key of 'share_dir' must be scalar or arrayref"}}}else {die "'module' key in 'share_dir' must be hashref"}}}else {die "'share_dir' must be hashref, arrayref or string"}return$p->{share_dir}}sub script_files {my$self=shift;for ($self->{properties}{script_files}){$_=shift if @_;next unless $_;return $_ if ref $_ eq 'HASH';return $_={map {$_,1}@$_ }if ref $_ eq 'ARRAY';die "'script_files' must be a hashref, arrayref, or string" if ref();return $_={map {$_,1}$self->_files_in($_)}if -d $_;return $_={$_=>1}}my%pl_files=map {File::Spec->canonpath($_)=>1}keys %{$self->PL_files || {}};my@bin_files=$self->_files_in('bin');my%bin_map=map {$_=>File::Spec->canonpath($_)}@bin_files;return $_={map {$_=>1}grep!$pl_files{$bin_map{$_}},@bin_files }}BEGIN {*scripts=\&script_files}{my%licenses=(perl=>'Perl_5',apache=>'Apache_2_0',apache_1_1=>'Apache_1_1',artistic=>'Artistic_1',artistic_2=>'Artistic_2',lgpl=>'LGPL_2_1',lgpl2=>'LGPL_2_1',lgpl3=>'LGPL_3_0',bsd=>'BSD',gpl=>'GPL_1',gpl2=>'GPL_2',gpl3=>'GPL_3',mit=>'MIT',mozilla=>'Mozilla_1_1',restrictive=>'Restricted',open_source=>undef,unrestricted=>undef,unknown=>undef,);my%license_urls=(perl=>'http://dev.perl.org/licenses/',apache=>'http://apache.org/licenses/LICENSE-2.0',apache_1_1=>'http://apache.org/licenses/LICENSE-1.1',artistic=>'http://opensource.org/licenses/artistic-license.php',artistic_2=>'http://opensource.org/licenses/artistic-license-2.0.php',lgpl=>'http://opensource.org/licenses/lgpl-license.php',lgpl2=>'http://opensource.org/licenses/lgpl-2.1.php',lgpl3=>'http://opensource.org/licenses/lgpl-3.0.html',bsd=>'http://opensource.org/licenses/bsd-license.php',gpl=>'http://opensource.org/licenses/gpl-license.php',gpl2=>'http://opensource.org/licenses/gpl-2.0.php',gpl3=>'http://opensource.org/licenses/gpl-3.0.html',mit=>'http://opensource.org/licenses/mit-license.php',mozilla=>'http://opensource.org/licenses/mozilla1.1.php',restrictive=>undef,open_source=>undef,unrestricted=>undef,unknown=>undef,);sub valid_licenses {return \%licenses}sub _license_url {return$license_urls{$_[1]}}}sub _software_license_class {my ($self,$license)=@_;if ($self->valid_licenses->{$license}&& eval {require Software::LicenseUtils;Software::LicenseUtils->VERSION(0.103009)}){my@classes=Software::LicenseUtils->guess_license_from_meta_key($license,1);if (@classes==1){eval "require $classes[0]";return$classes[0]}}LICENSE: for my$l ($self->valid_licenses->{$license },$license){next unless defined$l;my$trial="Software::License::" .$l;if (eval "require Software::License; Software::License->VERSION(0.014); require $trial; 1"){return$trial}}return}sub _software_license_object {my ($self)=@_;return unless defined(my$license=$self->license);my$class=$self->_software_license_class($license)or return;my$author=join(" & ",@{$self->dist_author})|| 'unknown';my$sl=eval {$class->new({holder=>$author})};if ($@){$self->log_warn("Error getting '$class' object: $@")}return$sl}sub _hash_merge {my ($self,$h,$k,$v)=@_;if (ref$h->{$k}eq 'ARRAY'){push @{$h->{$k}},ref$v ? @$v : $v}elsif (ref$h->{$k}eq 'HASH'){$h->{$k}{$_}=$v->{$_}foreach keys %$v}else {$h->{$k}=$v}}sub ACTION_distmeta {my ($self)=@_;$self->do_create_makefile_pl if$self->create_makefile_pl;$self->do_create_readme if$self->create_readme;$self->do_create_license if$self->create_license;$self->do_create_metafile}sub do_create_metafile {my$self=shift;return if$self->{wrote_metadata};my$p=$self->{properties};unless ($p->{license}){$self->log_warn("No license specified, setting license = 'unknown'\n");$p->{license}='unknown'}my@metafiles=($self->metafile,$self->metafile2);$self->delete_filetree($_)for@metafiles;local@INC=@INC;if (($self->module_name || '')eq 'Module::Build'){$self->depends_on('config_data');push@INC,File::Spec->catdir($self->blib,'lib')}my$meta_obj=$self->_get_meta_object(quiet=>1,fatal=>1,auto=>1);my@created=$self->_write_meta_files($meta_obj,'META');if (@created){$self->{wrote_metadata}=1;$self->_add_to_manifest('MANIFEST',$_)for@created}return 1}sub _write_meta_files {my$self=shift;my ($meta,$file)=@_;$file =~ s{\.(?:yml|json)$}{};my@created;push@created,"$file\.yml" if$meta && $meta->save("$file\.yml",{version=>"1.4"});push@created,"$file\.json" if$meta && $meta->save("$file\.json");if (@created){$self->log_info("Created " .join(" and ",@created)."\n")}return@created}sub _get_meta_object {my$self=shift;my%args=@_;return unless$self->try_require("CPAN::Meta","2.142060");my$meta;eval {my$data=$self->get_metadata(fatal=>$args{fatal},auto=>$args{auto},);$data->{dynamic_config}=$args{dynamic}if defined$args{dynamic};$meta=CPAN::Meta->create($data)};if ($@ &&!$args{quiet}){$self->log_warn("Could not get valid metadata. Error is: $@\n")}return$meta}sub read_metafile {my$self=shift;my ($metafile)=@_;return unless$self->try_require("CPAN::Meta","2.110420");my$meta=CPAN::Meta->load_file($metafile);return$meta->as_struct({version=>"2.0"})}sub normalize_version {my ($self,$version)=@_;$version=0 unless defined$version and length$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%prereq_map=(requires=>[qw/runtime requires/],configure_requires=>[qw/configure requires/],build_requires=>[qw/build requires/ ],test_requires=>[qw/test requires/ ],test_recommends=>[qw/test recommends/ ],recommends=>[qw/runtime recommends/ ],conflicts=>[qw/runtime conflicts/ ],);sub _normalize_prereqs {my ($self)=@_;my$p=$self->{properties};my%prereq_types;for my$type ('configure_requires',@{$self->prereq_action_types}){if (exists$p->{$type}and keys %{$p->{$type}}){my ($phase,$relation)=@{$prereq_map{$type}};for my$mod (keys %{$p->{$type}}){$prereq_types{$phase}{$relation}{$mod}=$self->normalize_version($p->{$type}{$mod})}}}return \%prereq_types}sub _get_license {my$self=shift;my$license=$self->license;my ($meta_license,$meta_license_url);my$valid_licenses=$self->valid_licenses();if (my$sl=$self->_software_license_object){$meta_license=$sl->meta2_name;$meta_license_url=$sl->url}elsif (exists$valid_licenses->{$license}){$meta_license=$valid_licenses->{$license}? lc$valid_licenses->{$license}: $license;$meta_license_url=$self->_license_url($license)}else {$self->log_warn("Can not determine license type for '" .$self->license ."'\nSetting META license field to 'unknown'.\n");$meta_license='unknown'}return ($meta_license,$meta_license_url)}sub get_metadata {my ($self,%args)=@_;my$fatal=$args{fatal}|| 0;my$p=$self->{properties};$self->auto_config_requires if$args{auto};for my$f (qw(dist_name dist_version dist_author dist_abstract license)){my$field=$self->$f();unless (defined$field and length$field){my$err="ERROR: Missing required field '$f' for metafile\n";if ($fatal){die$err}else {$self->log_warn($err)}}}my%metadata=(name=>$self->dist_name,version=>$self->normalize_version($self->dist_version),author=>$self->dist_author,abstract=>$self->dist_abstract,generated_by=>"Module::Build version $Module::Build::VERSION",'meta-spec'=>{version=>'2',url=>'http://search.cpan.org/perldoc?CPAN::Meta::Spec',},dynamic_config=>exists$p->{dynamic_config}? $p->{dynamic_config}: 1,release_status=>$self->release_status,);my ($meta_license,$meta_license_url)=$self->_get_license;$metadata{license}=[$meta_license ];$metadata{resources}{license}=[$meta_license_url ]if defined$meta_license_url;$metadata{prereqs}=$self->_normalize_prereqs;if (exists$p->{no_index}){$metadata{no_index}=$p->{no_index}}elsif (my$pkgs=eval {$self->find_dist_packages}){$metadata{provides}=$pkgs if %$pkgs}else {$self->log_warn("$@\nWARNING: Possible missing or corrupt 'MANIFEST' file.\n" ."Nothing to enter for 'provides' field in metafile.\n")}if (my$add=$self->meta_add){if (not exists$add->{'meta-spec'}or $add->{'meta-spec'}{version}!=2){require CPAN::Meta::Converter;if (CPAN::Meta::Converter->VERSION('2.141170')){$add=CPAN::Meta::Converter->new($add)->upgrade_fragment;delete$add->{prereqs}}else {$self->log_warn("Can't meta_add without CPAN::Meta 2.141170")}}while (my($k,$v)=each %{$add}){$metadata{$k}=$v}}if (my$merge=$self->meta_merge){if (eval {require CPAN::Meta::Merge}){%metadata=%{CPAN::Meta::Merge->new(default_version=>'1.4')->merge(\%metadata,$merge)}}else {$self->log_warn("Can't merge without CPAN::Meta::Merge")}}return \%metadata}sub prepare_metadata {my ($self,$node,$keys,$args)=@_;unless (ref$node eq 'HASH'){croak "prepare_metadata() requires a hashref argument to hold output\n"}croak 'Keys argument to prepare_metadata is no longer supported' if$keys;%{$node}=%{$self->get_meta(%{$args})};return$node}sub _read_manifest {my ($self,$file)=@_;return undef unless -e $file;require ExtUtils::Manifest;local ($^W,$ExtUtils::Manifest::Quiet)=(0,1);return scalar ExtUtils::Manifest::maniread($file)}sub find_dist_packages {my$self=shift;my$manifest=$self->_read_manifest('MANIFEST')or die "Can't find dist packages without a MANIFEST file\nRun 'Build manifest' to generate one\n";my%dist_files=map {$self->localize_file_path($_)=>$_}keys %$manifest;my@pm_files=sort grep {$_ !~ m{^t}}grep {exists$dist_files{$_}}keys %{$self->find_pm_files};return$self->find_packages_in_files(\@pm_files,\%dist_files)}sub find_packages_in_files {my ($self,$file_list,$filename_map)=@_;my(%prime,%alt);for my$file (@{$file_list}){my$mapped_filename=$filename_map->{$file};my@path=split(/\//,$mapped_filename);(my$prime_package=join('::',@path[1..$#path]))=~ s/\.pm$//;my$pm_info=Module::Metadata->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);if ($package eq $prime_package){if (exists($prime{$package})){die "Unexpected conflict in '$package'; multiple versions found.\n"}else {$prime{$package}{file}=$mapped_filename;$prime{$package}{version}=$version if defined($version)}}else {push(@{$alt{$package}},{file=>$mapped_filename,version=>$version,})}}}for my$package (sort keys(%alt)){my$result=$self->_resolve_module_versions($alt{$package});if (exists($prime{$package})){if ($result->{err}){$self->log_warn("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 ($self->compare_versions($prime{$package}{version},'!=',$result->{version})){$self->log_warn("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}){$self->log_warn("Found conflicting versions for package '$package'\n" .$result->{err})}$prime{$package}{file}=$result->{file};$prime{$package}{version}=$result->{version}if defined($result->{version})}}for my$provides (values%prime){if ($provides->{version}){$provides->{version}=$self->normalize_version($provides->{version})}else {delete$provides->{version}}}return \%prime}sub _resolve_module_versions {my$self=shift;my$packages=shift;my($file,$version);my$err='';for my$p (@$packages){if (defined($p->{version})){if (defined($version)){if ($self->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 make_tarball {my ($self,$dir,$file)=@_;$file ||= $dir;$self->log_info("Creating $file.tar.gz\n");if ($self->{args}{tar}){my$tar_flags=$self->verbose ? 'cvf' : 'cf';$self->do_system($self->split_like_shell($self->{args}{tar}),$tar_flags,"$file.tar",$dir);$self->do_system($self->split_like_shell($self->{args}{gzip}),"$file.tar")if$self->{args}{gzip}}else {eval {require Archive::Tar && Archive::Tar->VERSION(1.09);1}or die "You must install Archive::Tar 1.09+ to make a distribution tarball\n"."or specify a binary tar program with the '--tar' option.\n"."See the documentation for the 'dist' action.\n";my$files=$self->rscan_dir($dir);$Archive::Tar::DO_NOT_USE_PREFIX=(grep {length($_)>= 100}@$files)? 0 : 1;my$tar=Archive::Tar->new;$tar->add_files(@$files);for my$f ($tar->get_files){$f->mode($f->mode & ~022)}$tar->write("$file.tar.gz",1)}}sub install_path {my$self=shift;my($type,$value)=(@_,'<empty>');Carp::croak('Type argument missing')unless defined($type);my$map=$self->{properties}{install_path};return$map unless @_;unless (defined($value)){delete($map->{$type});return undef}if ($value eq '<empty>'){return undef unless exists$map->{$type};return$map->{$type}}return$map->{$type}=$value}sub install_sets {my ($self,$dirs,$key,$value)=@_;$dirs=$self->installdirs unless defined$dirs;if (@_==4 && defined$dirs && defined$key){$self->{properties}{install_sets}{$dirs}{$key}=$value}my$map={$self->_merge_arglist($self->{properties}{install_sets},$self->_default_install_paths->{install_sets})};if (defined$dirs && defined$key){return$map->{$dirs}{$key}}elsif (defined$dirs){return$map->{$dirs}}else {croak "Can't determine installdirs for install_sets()"}}sub original_prefix {my ($self,$key,$value)=@_;if (@_==3 && defined$key){$self->{properties}{original_prefix}{$key}=$value}my$map={$self->_merge_arglist($self->{properties}{original_prefix},$self->_default_install_paths->{original_prefix})};return$map unless defined$key;return$map->{$key}}sub install_base_relpaths {my$self=shift;if (@_ > 1){$self->_set_relpaths($self->{properties}{install_base_relpaths},@_)}my$map={$self->_merge_arglist($self->{properties}{install_base_relpaths},$self->_default_install_paths->{install_base_relpaths})};return$map unless @_;my$relpath=$map->{$_[0]};return defined$relpath ? File::Spec->catdir(@$relpath): undef}sub prefix_relpaths {my$self=shift;my$installdirs=shift || $self->installdirs or croak "Can't determine installdirs for prefix_relpaths()";if (@_ > 1){$self->{properties}{prefix_relpaths}{$installdirs}||= {};$self->_set_relpaths($self->{properties}{prefix_relpaths}{$installdirs},@_)}my$map={$self->_merge_arglist($self->{properties}{prefix_relpaths}{$installdirs},$self->_default_install_paths->{prefix_relpaths}{$installdirs})};return$map unless @_;my$relpath=$map->{$_[0]};return defined$relpath ? File::Spec->catdir(@$relpath): undef}sub _set_relpaths {my$self=shift;my($map,$type,$value)=@_;Carp::croak('Type argument missing')unless defined($type);if (!defined($value)){$map->{$type}=undef;return}else {Carp::croak("Value must be a relative path")if File::Spec::Unix->file_name_is_absolute($value);my@value=split(/\//,$value);$map->{$type}=\@value}}sub prefix_relative {my ($self,$type)=@_;my$installdirs=$self->installdirs;my$relpath=$self->install_sets($installdirs)->{$type};return$self->_prefixify($relpath,$self->original_prefix($installdirs),$type,)}sub _prefixify {my($self,$path,$sprefix,$type)=@_;my$rprefix=$self->prefix;$rprefix .= '/' if$sprefix =~ m|/$|;$self->log_verbose(" prefixify $path from $sprefix to $rprefix\n")if defined($path)&& length($path);if(!defined($path)|| (length($path)==0)){$self->log_verbose(" no path to prefixify, falling back to default.\n");return$self->_prefixify_default($type,$rprefix)}elsif(!File::Spec->file_name_is_absolute($path)){$self->log_verbose(" path is relative, not prefixifying.\n")}elsif($path !~ s{^\Q$sprefix\E\b}{}s){$self->log_verbose(" cannot prefixify, falling back to default.\n");return$self->_prefixify_default($type,$rprefix)}$self->log_verbose(" now $path in $rprefix\n");return$path}sub _prefixify_default {my$self=shift;my$type=shift;my$rprefix=shift;my$default=$self->prefix_relpaths($self->installdirs,$type);if(!$default){$self->log_verbose(" no default install location for type '$type', using prefix '$rprefix'.\n");return$rprefix}else {return$default}}sub install_destination {my ($self,$type)=@_;return$self->install_path($type)if$self->install_path($type);if ($self->install_base){my$relpath=$self->install_base_relpaths($type);return$relpath ? File::Spec->catdir($self->install_base,$relpath): undef}if ($self->prefix){my$relpath=$self->prefix_relative($type);return$relpath ? File::Spec->catdir($self->prefix,$relpath): undef}return$self->install_sets($self->installdirs)->{$type}}sub install_types {my$self=shift;my%types;if ($self->install_base){%types=%{$self->install_base_relpaths}}elsif ($self->prefix){%types=%{$self->prefix_relpaths}}else {%types=%{$self->install_sets($self->installdirs)}}%types=(%types,%{$self->install_path});return sort keys%types}sub install_map {my ($self,$blib)=@_;$blib ||= $self->blib;my(%map,@skipping);for my$type ($self->install_types){my$localdir=File::Spec->catdir($blib,$type);next unless -e $localdir;if (my$dest=$self->install_destination($type)){$map{$localdir}=$dest}else {push(@skipping,$type)}}$self->log_warn("WARNING: Can't figure out install path for types: @skipping\n" ."Files will not be installed.\n")if@skipping;if ($self->create_packlist and my$module_name=$self->module_name){my$archdir=$self->install_destination('arch');my@ext=split /::/,$module_name;$map{write}=File::Spec->catfile($archdir,'auto',@ext,'.packlist')}if (length(my$destdir=$self->destdir || '')){for (keys%map){my ($volume,$path,$file)=File::Spec->splitpath($map{$_},0);my@dirs=File::Spec->splitdir($path);$path=File::Spec->catdir($destdir,@dirs);if ($file ne ''){$map{$_}=File::Spec->catfile($path,$file)}else {$map{$_}=$path}}}$map{read}='';return \%map}sub depends_on {my$self=shift;for my$action (@_){$self->_call_action($action)}}sub rscan_dir {my ($self,$dir,$pattern)=@_;my@result;local $_;my$subr=!$pattern ? sub {push@result,$File::Find::name}: !ref($pattern)|| (ref$pattern eq 'Regexp')? sub {push@result,$File::Find::name if /$pattern/}: ref($pattern)eq 'CODE' ? sub {push@result,$File::Find::name if$pattern->()}: die "Unknown pattern type";File::Find::find({wanted=>$subr,no_chdir=>1,preprocess=>sub {sort @_}},$dir);return \@result}sub delete_filetree {my$self=shift;my$deleted=0;for (@_){next unless -e $_;$self->log_verbose("Deleting $_\n");File::Path::rmtree($_,0,0);die "Couldn't remove '$_': $!\n" if -e $_;$deleted++}return$deleted}sub autosplit_file {my ($self,$file,$to)=@_;require AutoSplit;my$dir=File::Spec->catdir($to,'lib','auto');AutoSplit::autosplit($file,$dir)}sub cbuilder {my$self=shift;my$s=$self->{stash};return$s->{_cbuilder}if$s->{_cbuilder};require ExtUtils::CBuilder;return$s->{_cbuilder}=ExtUtils::CBuilder->new(config=>$self->config,($self->quiet ? (quiet=>1): ()),)}sub have_c_compiler {my ($self)=@_;my$p=$self->{properties};return$p->{_have_c_compiler}if defined$p->{_have_c_compiler};$self->log_verbose("Checking if compiler tools configured... ");my$b=$self->cbuilder;my$have=$b && eval {$b->have_compiler};$self->log_verbose($have ? "ok.\n" : "failed.\n");return$p->{_have_c_compiler}=$have}sub compile_c {my ($self,$file,%args)=@_;if (!$self->have_c_compiler){die "Error: no compiler detected to compile '$file'. Aborting\n"}my$b=$self->cbuilder;my$obj_file=$b->object_file($file);$self->add_to_cleanup($obj_file);return$obj_file if$self->up_to_date($file,$obj_file);$b->compile(source=>$file,defines=>$args{defines},object_file=>$obj_file,include_dirs=>$self->include_dirs,extra_compiler_flags=>$self->extra_compiler_flags,);return$obj_file}sub link_c {my ($self,$spec)=@_;my$p=$self->{properties};$self->add_to_cleanup($spec->{lib_file});my$objects=$p->{objects}|| [];return$spec->{lib_file}if$self->up_to_date([$spec->{obj_file},@$objects],$spec->{lib_file});my$module_name=$spec->{module_name}|| $self->module_name;$self->cbuilder->link(module_name=>$module_name,objects=>[$spec->{obj_file},@$objects],lib_file=>$spec->{lib_file},extra_linker_flags=>$self->extra_linker_flags);return$spec->{lib_file}}sub compile_xs {my ($self,$file,%args)=@_;$self->log_verbose("$file -> $args{outfile}\n");if (eval {require ExtUtils::ParseXS;1}){ExtUtils::ParseXS::process_file(filename=>$file,prototypes=>0,output=>$args{outfile},)}else {my$xsubpp=Module::Metadata->find_module_by_name('ExtUtils::xsubpp')or die "Can't find ExtUtils::xsubpp in INC (@INC)";my@typemaps;push@typemaps,Module::Metadata->find_module_by_name('ExtUtils::typemap',\@INC);my$lib_typemap=Module::Metadata->find_module_by_name('typemap',[File::Basename::dirname($file),File::Spec->rel2abs('.')]);push@typemaps,$lib_typemap if$lib_typemap;@typemaps=map {+'-typemap',$_}@typemaps;my$cf=$self->{config};my$perl=$self->{properties}{perl};my@command=($perl,"-I".$cf->get('installarchlib'),"-I".$cf->get('installprivlib'),$xsubpp,'-noprototypes',@typemaps,$file);$self->log_info("@command\n");open(my$fh,'>',$args{outfile})or die "Couldn't write $args{outfile}: $!";print {$fh}$self->_backticks(@command);close$fh}}sub split_like_shell {my ($self,$string)=@_;return ()unless defined($string);return @$string if ref$string eq 'ARRAY';$string =~ s/^\s+|\s+$//g;return ()unless length($string);return Text::ParseWords::shellwords($string)}sub oneliner {my($self,$cmd,$switches,$args)=@_;$switches=[]unless defined$switches;$args=[]unless defined$args;$cmd =~ s{^\n+}{};$cmd =~ s{\n+$}{};my$perl=ref($self)? $self->perl : $self->find_perl_interpreter;return$self->_quote_args($perl,@$switches,'-e',$cmd,@$args)}sub run_perl_script {my ($self,$script,$preargs,$postargs)=@_;for ($preargs,$postargs){$_=[$self->split_like_shell($_)]unless ref()}return$self->run_perl_command([@$preargs,$script,@$postargs])}sub run_perl_command {my ($self,$args)=@_;$args=[$self->split_like_shell($args)]unless ref($args);my$perl=ref($self)? $self->perl : $self->find_perl_interpreter;local$ENV{PERL5LIB}=join$self->config('path_sep'),$self->_added_to_INC;return$self->do_system($perl,@$args)}sub _infer_xs_spec {my$self=shift;my$file=shift;my$cf=$self->{config};my%spec;my($v,$d,$f)=File::Spec->splitpath($file);my@d=File::Spec->splitdir($d);(my$file_base=$f)=~ s/\.[^.]+$//i;$spec{base_name}=$file_base;$spec{src_dir}=File::Spec->catpath($v,$d,'');shift(@d)while@d && ($d[0]eq 'lib' || $d[0]eq '');pop(@d)while@d && $d[-1]eq '';$spec{module_name}=join('::',(@d,$file_base));$spec{archdir}=File::Spec->catdir($self->blib,'arch','auto',@d,$file_base);$spec{c_file}=File::Spec->catfile($spec{src_dir},"${file_base}.c");$spec{obj_file}=File::Spec->catfile($spec{src_dir},"${file_base}".$cf->get('obj_ext'));require DynaLoader;my$modfname=defined&DynaLoader::mod2fname ? DynaLoader::mod2fname([@d,$file_base]): $file_base;$spec{bs_file}=File::Spec->catfile($spec{archdir},"$modfname.bs");$spec{lib_file}=File::Spec->catfile($spec{archdir},"$modfname.".$cf->get('dlext'));return \%spec}sub process_xs {my ($self,$file)=@_;my$spec=$self->_infer_xs_spec($file);(my$file_base=$file)=~ s/\.[^.]+$//;$self->add_to_cleanup($spec->{c_file});unless ($self->up_to_date($file,$spec->{c_file})){$self->compile_xs($file,outfile=>$spec->{c_file})}my$v=$self->dist_version;$self->compile_c($spec->{c_file},defines=>{VERSION=>qq{"$v"},XS_VERSION=>qq{"$v"}});File::Path::mkpath($spec->{archdir},0,oct(777))unless -d $spec->{archdir};$self->add_to_cleanup($spec->{bs_file});unless ($self->up_to_date($file,$spec->{bs_file})){require ExtUtils::Mkbootstrap;$self->log_info("ExtUtils::Mkbootstrap::Mkbootstrap('$spec->{bs_file}')\n");ExtUtils::Mkbootstrap::Mkbootstrap($spec->{bs_file});open(my$fh,'>>',$spec->{bs_file});utime((time)x2,$spec->{bs_file})}$self->link_c($spec)}sub do_system {my ($self,@cmd)=@_;$self->log_verbose("@cmd\n");my%seen;my$sep=$self->config('path_sep');local$ENV{PERL5LIB}=(!exists($ENV{PERL5LIB})? '' : length($ENV{PERL5LIB})< 500 ? $ENV{PERL5LIB}: join$sep,grep {!$seen{$_}++ and -d $_}split($sep,$ENV{PERL5LIB}));my$status=system(@cmd);if ($status and $! =~ /Argument list too long/i){my$env_entries='';for (sort keys%ENV){$env_entries .= "$_=>".length($ENV{$_})."; "}warn "'Argument list' was 'too long', env lengths are $env_entries"}return!$status}sub copy_if_modified {my$self=shift;my%args=(@_ > 3 ? (@_): (from=>shift,to_dir=>shift,flatten=>shift));$args{verbose}=!$self->quiet unless exists$args{verbose};my$file=$args{from};unless (defined$file and length$file){die "No 'from' parameter given to copy_if_modified"}$args{flatten}=1 if File::Spec->file_name_is_absolute($file);my$to_path;if (defined$args{to}and length$args{to}){$to_path=$args{to}}elsif (defined$args{to_dir}and length$args{to_dir}){$to_path=File::Spec->catfile($args{to_dir},$args{flatten}? File::Basename::basename($file): $file)}else {die "No 'to' or 'to_dir' parameter given to copy_if_modified"}return if$self->up_to_date($file,$to_path);{local$self->{properties}{quiet}=1;$self->delete_filetree($to_path)}File::Path::mkpath(File::Basename::dirname($to_path),0,oct(777));$self->log_verbose("Copying $file -> $to_path\n");if ($^O eq 'os2'){chmod 0666,$to_path;File::Copy::syscopy($file,$to_path,0x1)or die "Can't copy('$file', '$to_path'): $!"}else {File::Copy::copy($file,$to_path)or die "Can't copy('$file', '$to_path'): $!"}my$mode=oct(444)| ($self->is_executable($file)? oct(111): 0);chmod($mode,$to_path);return$to_path}sub up_to_date {my ($self,$source,$derived)=@_;$source=[$source]unless ref$source;$derived=[$derived]unless ref$derived;return 0 if @$source &&!@$derived || grep {not -e}@$derived;my$most_recent_source=time / (24*60*60);for my$file (@$source){unless (-e $file){$self->log_warn("Can't find source file $file for up-to-date check");next}$most_recent_source=-M _ if -M _ < $most_recent_source}for my$derived (@$derived){return 0 if -M $derived > $most_recent_source}return 1}sub dir_contains {my ($self,$first,$second)=@_;($first,$second)=map File::Spec->canonpath($_),($first,$second);my@first_dirs=File::Spec->splitdir($first);my@second_dirs=File::Spec->splitdir($second);return 0 if@second_dirs < @first_dirs;my$is_same=($self->_case_tolerant ? sub {lc(shift())eq lc(shift())}: sub {shift()eq shift()});while (@first_dirs){return 0 unless$is_same->(shift@first_dirs,shift@second_dirs)}return 1}1;
112
113 ERRORS/WARNINGS FOUND IN PREREQUISITES. You may wish to install the versions
114 of the modules indicated above before proceeding with this installation
115
116 EOF
117 * FATAL ERROR: Perl interpreter mismatch. Configuration was initially
118 created with '$self->{properties}{perl}'
119 but we are now using '$perl'. You must
120 run 'Build realclean' or 'make realclean' and re-configure.
121 DIEFATAL
122 * WARNING: Configuration was initially created with Module::Build
123 version '$self->{properties}{mb_version}' but we are now using version '$mb_version'.
124 If errors occur, you must re-run the Build.PL or Makefile.PL script.
125 MISMATCH
126 ERROR: This build seems to be unattended, but there is no default value
127 for this question. Aborting.
128 EOF
129 package $opts{class};
130 use $pack;
131 \@ISA = qw($pack);
132 $opts{code}
133 1;
134 EOF
135 No 'module_name' was provided and it could not be inferred
136 from other properties. This will prevent a packlist from
137 being written for this file. Please set either 'module_name'
138 or 'dist_version_from' in Build.PL.
139 END_WARN
140 Bundling in inc/ is disabled because ExtUtils::Installed could not
141 create a list of your installed modules. Here is the error:
142 $@
143 EUI_ERROR
144 Could not find a packlist for '$mod'. If it's a core module, try
145 force installing it from CPAN.
146 NO_PACKLIST
147 Module::Build was not found in configure_requires! Adding it now
148 automatically as: configure_requires => { 'Module::Build' => $ver }
149 EOM
150 Warning: ExtUtils::CBuilder not installed or no compiler detected
151 Proceeding with configuration, but compilation may fail during Build
152
153 EOM
154 if ($INC[-1] ne '.') {
155 push @INC, '.';
156 }
157 END
158 $shebang
159
160 use strict;
161 use Cwd;
162 use File::Basename;
163 use File::Spec;
164
165 sub magic_number_matches {
166 return 0 unless -e '$q{magic_numfile}';
167 my \$FH;
168 open \$FH, '<','$q{magic_numfile}' or return 0;
169 my \$filenum = <\$FH>;
170 close \$FH;
171 return \$filenum == $magic_number;
172 }
173
174 my \$progname;
175 my \$orig_dir;
176 BEGIN {
177 \$^W = 1; # Use warnings
178 \$progname = basename(\$0);
179 \$orig_dir = Cwd::cwd();
180 my \$base_dir = '$q{base_dir}';
181 if (!magic_number_matches()) {
182 unless (chdir(\$base_dir)) {
183 die ("Couldn't chdir(\$base_dir), aborting\\n");
184 }
185 unless (magic_number_matches()) {
186 die ("Configuration seems to be out of date, please re-run 'perl Build.PL' again.\\n");
187 }
188 }
189 unshift \@INC,
190 (
191 $quoted_INC
192 );
193 $dot_in_inc_code
194 }
195
196 close(*DATA) unless eof(*DATA); # ensure no open handles to this script
197
198 use $build_package;
199 Module::Build->VERSION(q{$config_requires});
200
201 # Some platforms have problems setting \$^X in shebang contexts, fix it up here
202 \$^X = Module::Build->find_perl_interpreter;
203
204 if (-e 'Build.PL' and not $build_package->up_to_date('Build.PL', \$progname)) {
205 warn "Warning: Build.PL has been altered. You may need to run 'perl Build.PL' again.\\n";
206 }
207
208 # This should have just enough arguments to be able to bootstrap the rest.
209 my \$build = $build_package->resume (
210 properties => {
211 config_dir => '$q{config_dir}',
212 orig_dir => \$orig_dir,
213 },
214 );
215
216 \$build->dispatch;
217 EOF
218
219 Usage: $0 <action> --arg1=value --arg2=value ...
220 Example: $0 test --verbose=1
221
222 Actions defined:
223 EOF
224 Can't create LICENSE file: '$l' is not a valid license key
225 or Software::License subclass;
226 HERE
227 Cannot create README: can't determine which file contains documentation;
228 Must supply either 'dist_version_from', or 'module_name' parameter.
229 EOF
230 # Avoid configuration metadata file
231 ^MYMETA\.
232
233 # Avoid Module::Build generated and utility files.
234 \bBuild$
235 \bBuild.bat$
236 \b_build
237 \bBuild.COM$
238 \bBUILD.COM$
239 \bbuild.com$
240 ^MANIFEST\.SKIP
241
242 # Avoid archives of this distribution
243 EOF
244 MODULE_BUILD_BASE
245
246 $fatpacked{"Module/Build/Compat.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_COMPAT';
247 package Module::Build::Compat;use strict;use warnings;our$VERSION='0.4224';use File::Basename ();use File::Spec;use Config;use Module::Build;use Module::Metadata;use version;use Data::Dumper;my%convert_installdirs=(PERL=>'core',SITE=>'site',VENDOR=>'vendor',);my%makefile_to_build=(TEST_VERBOSE=>'verbose',VERBINST=>'verbose',INC=>sub {map {(extra_compiler_flags=>$_)}Module::Build->split_like_shell(shift)},POLLUTE=>sub {(extra_compiler_flags=>'-DPERL_POLLUTE')},INSTALLDIRS=>sub {(installdirs=>$convert_installdirs{uc shift()})},LIB=>sub {my$lib=shift;my%config=(installprivlib=>$lib,installsitelib=>$lib,installarchlib=>"$lib/$Config{archname}",installsitearch=>"$lib/$Config{archname}");return map {(config=>"$_=$config{$_}")}sort keys%config},(map {my$name=$_;$name=>sub {my@ret=(config=>lc($name)."=" .shift);print STDERR "# Converted to @ret\n";return@ret}}qw(INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR)),map {$_,lc($_)}qw(DESTDIR PREFIX INSTALL_BASE UNINST),);my%macro_to_build=%makefile_to_build;delete$macro_to_build{LIB};sub _merge_prereq {my ($req,$breq)=@_;$req ||= {};$breq ||= {};for my$p ($req,$breq){for my$k (sort keys %$p){next if$k eq 'perl';my$v_obj=eval {version->new($p->{$k})};if (!defined$v_obj){die "A prereq of the form '$p->{$k}' for '$k' is not supported by Module::Build::Compat ( use a simpler version like '0.05' or 'v1.4.25' )\n"}if ($v_obj->is_qv){my$proper_ver=$v_obj->numify;warn "Dotted-decimal prereq '$p->{$k}' for '$k' is not portable - converting it to '$proper_ver'\n";$p->{$k}=$proper_ver}}}my$merge={%$req };for my$k (keys %$breq){my$v1=$merge->{$k}|| 0;my$v2=$breq->{$k};$merge->{$k}=$v1 > $v2 ? $v1 : $v2}return %$merge}sub create_makefile_pl {my ($package,$type,$build,%args)=@_;die "Don't know how to build Makefile.PL of type '$type'" unless$type =~ /^(small|passthrough|traditional)$/;if ($type eq 'passthrough'){$build->log_warn(<<"HERE")}my$fh;if ($args{fh}){$fh=$args{fh}}else {$args{file}||= 'Makefile.PL';local$build->{properties}{quiet}=1;$build->delete_filetree($args{file});open($fh,'>',"$args{file}")or die "Can't write $args{file}: $!"}print {$fh}"# Note: this file was auto-generated by ",__PACKAGE__," version $VERSION\n";my$requires=$build->requires;if (my$minimum_perl=$requires->{perl}){my$min_ver=version->new($minimum_perl)->numify;print {$fh}"require $min_ver;\n"}my$subclass_load='';if (ref($build)ne "Module::Build"){my$subclass_dir=$package->subclass_dir($build);if (File::Spec->file_name_is_absolute($subclass_dir)){my$base_dir=$build->base_dir;if ($build->dir_contains($base_dir,$subclass_dir)){$subclass_dir=File::Spec->abs2rel($subclass_dir,$base_dir);$subclass_dir=$package->unixify_dir($subclass_dir);$subclass_load="use lib '$subclass_dir';"}}else {$subclass_dir=$package->unixify_dir($subclass_dir);$subclass_load="use lib '$subclass_dir';"}}if ($type eq 'small'){printf {$fh}<<'EOF',$subclass_load,ref($build),ref($build)}elsif ($type eq 'passthrough'){printf {$fh}<<'EOF',$subclass_load,ref($build),ref($build)}elsif ($type eq 'traditional'){my (%MM_Args,%prereq);if (eval "use Tie::IxHash 1.2; 1"){tie%MM_Args,'Tie::IxHash';tie%prereq,'Tie::IxHash'}my%name=($build->module_name ? (NAME=>$build->module_name): (DISTNAME=>$build->dist_name));my%version=($build->dist_version_from ? (VERSION_FROM=>$build->dist_version_from): (VERSION=>$build->dist_version));%MM_Args=(%name,%version);%prereq=_merge_prereq($build->requires,$build->build_requires);%prereq=map {$_,$prereq{$_}}sort keys%prereq;delete$prereq{perl};$MM_Args{PREREQ_PM}=\%prereq;$MM_Args{INSTALLDIRS}=$build->installdirs eq 'core' ? 'perl' : $build->installdirs;$MM_Args{EXE_FILES}=[sort keys %{$build->script_files}]if$build->script_files;$MM_Args{PL_FILES}=$build->PL_files || {};if ($build->recursive_test_files){$MM_Args{test}={TESTS=>join q{ },$package->_test_globs($build)}}local$Data::Dumper::Terse=1;my$args=Data::Dumper::Dumper(\%MM_Args);$args =~ s/\{(.*)\}/($1)/s;print$fh <<"EOF"}}sub _test_globs {my ($self,$build)=@_;return map {File::Spec->catfile($_,'*.t')}@{$build->rscan_dir('t',sub {-d $File::Find::name})}}sub subclass_dir {my ($self,$build)=@_;return (Module::Metadata->find_module_dir_by_name(ref$build)|| File::Spec->catdir($build->config_dir,'lib'))}sub unixify_dir {my ($self,$path)=@_;return join '/',File::Spec->splitdir($path)}sub makefile_to_build_args {my$class=shift;my@out;for my$arg (@_){next if$arg eq '';my ($key,$val)=($arg =~ /^(\w+)=(.+)/ ? ($1,$2): die "Malformed argument '$arg'");($val)=Module::Build->_detildefy($val)if$val =~ /^~/;if (exists$makefile_to_build{$key}){my$trans=$makefile_to_build{$key};push@out,$class->_argvify(ref($trans)? $trans->($val): ($trans=>$val))}elsif (exists$Config{lc($key)}){push@out,$class->_argvify(config=>lc($key)."=$val")}else {push@out,$class->_argvify("\L$key"=>$val)}}return@out}sub _argvify {my ($self,@pairs)=@_;my@out;while (@pairs){my ($k,$v)=splice@pairs,0,2;push@out,("--$k",$v)}return@out}sub makefile_to_build_macros {my@out;my%config;for my$macro (sort keys%macro_to_build){my$trans=$macro_to_build{$macro};next unless exists$ENV{$macro}&& length$ENV{$macro};my$val=$ENV{$macro};my@args=ref($trans)? $trans->($val): ($trans=>$val);while (@args){my ($k,$v)=splice(@args,0,2);if ($k eq 'config'){if ($v =~ /^([^=]+)=(.*)$/){$config{$1}=$2}else {warn "Couldn't parse config '$v'\n"}}else {push@out,($k=>$v)}}}push@out,(config=>\%config)if%config;return@out}sub run_build_pl {my ($pack,%in)=@_;$in{script}||= 'Build.PL';my@args=$in{args}? $pack->makefile_to_build_args(@{$in{args}}): ();print "# running $in{script} @args\n";Module::Build->run_perl_script($in{script},[],\@args)or die "Couldn't run $in{script}: $!"}sub fake_makefile {my ($self,%args)=@_;unless (exists$args{build_class}){warn "Unknown 'build_class', defaulting to 'Module::Build'\n";$args{build_class}='Module::Build'}my$class=$args{build_class};my$perl=$class->find_perl_interpreter;$perl='MCR ' .$perl if$self->_is_vms_mms;my$noop=($class->is_windowsish ? 'rem>nul' : $self->_is_vms_mms ? 'Continue' : 'true');my$filetype=$class->is_vmsish ? '.COM' : '';my$Build='Build' .$filetype .' --makefile_env_macros 1';my$unlink=$class->oneliner('1 while unlink $ARGV[0]',[],[$args{makefile}]);$unlink =~ s/\$/\$\$/g unless$class->is_vmsish;my$maketext=join '',map {"$_=\n"}sort keys%macro_to_build;$maketext .= ($^O eq 'os2' ? "SHELL = sh\n\n" : $^O eq 'MSWin32' && $Config{make}=~ /gmake/ ? "SHELL = $ENV{COMSPEC}\n\n" : "\n\n");$maketext .= <<"EOF";for my$action ($class->known_actions){next if$action =~ /^(all|distclean|realclean|force_do_it)$/;$maketext .= <<"EOF"}if ($self->_is_vms_mms){$maketext .= "\n.FIRST\n\t\@ $noop\n";for my$macro (sort keys%macro_to_build){$maketext .= ".IFDEF $macro\n\tDEFINE $macro \"\$($macro)\"\n.ENDIF\n"}$maketext .= "\n"}else {$maketext .= "\n.EXPORT : " .join(' ',sort keys%macro_to_build)."\n\n"}return$maketext}sub fake_prereqs {my$file=File::Spec->catfile('_build','prereqs');open(my$fh,'<',"$file")or die "Can't read $file: $!";my$prereqs=eval do {local $/;<$fh>};close$fh;my%merged=_merge_prereq($prereqs->{requires},$prereqs->{build_requires});my@prereq;for (sort keys%merged){next if $_ eq 'perl';push@prereq,"$_=>q[$merged{$_}]"}return unless@prereq;return "# PREREQ_PM => { " .join(", ",@prereq)." }\n\n"}sub write_makefile {my ($pack,%in)=@_;unless (exists$in{build_class}){warn "Unknown 'build_class', defaulting to 'Module::Build'\n";$in{build_class}='Module::Build'}my$class=$in{build_class};$in{makefile}||= $pack->_is_vms_mms ? 'Descrip.MMS' : 'Makefile';open MAKE,"> $in{makefile}" or die "Cannot write $in{makefile}: $!";print MAKE$pack->fake_prereqs;print MAKE$pack->fake_makefile(%in);close MAKE}sub _is_vms_mms {return Module::Build->is_vmsish && ($Config{make}=~ m/MM[SK]/i)}1;
248
249 IMPORTANT NOTE: The '$type' style of Makefile.PL is deprecated and
250 may be removed in a future version of Module::Build in favor of the
251 'configure_requires' property. See Module::Build::Compat
252 documentation for details.
253
254 HERE
255 use Module::Build::Compat 0.02;
256 %s
257 Module::Build::Compat->run_build_pl(args => \@ARGV);
258 require %s;
259 Module::Build::Compat->write_makefile(build_class => '%s');
260 EOF
261
262 unless (eval "use Module::Build::Compat 0.02; 1" ) {
263 print "This module requires Module::Build to install itself.\n";
264
265 require ExtUtils::MakeMaker;
266 my $yn = ExtUtils::MakeMaker::prompt
267 (' Install Module::Build now from CPAN?', 'y');
268
269 unless ($yn =~ /^y/i) {
270 die " *** Cannot install without Module::Build. Exiting ...\n";
271 }
272
273 require Cwd;
274 require File::Spec;
275 require CPAN;
276
277 # Save this 'cause CPAN will chdir all over the place.
278 my $cwd = Cwd::cwd();
279
280 CPAN::Shell->install('Module::Build::Compat');
281 CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
282 or die "Couldn't install Module::Build, giving up.\n";
283
284 chdir $cwd or die "Cannot chdir() back to $cwd: $!";
285 }
286 eval "use Module::Build::Compat 0.02; 1" or die $@;
287 %s
288 Module::Build::Compat->run_build_pl(args => \@ARGV);
289 my $build_script = 'Build';
290 $build_script .= '.com' if $^O eq 'VMS';
291 exit(0) unless(-e $build_script); # cpantesters convention
292 require %s;
293 Module::Build::Compat->write_makefile(build_class => '%s');
294 EOF
295 use ExtUtils::MakeMaker;
296 WriteMakefile
297 $args;
298 EOF
299 all : force_do_it
300 $perl $Build
301 realclean : force_do_it
302 $perl $Build realclean
303 $unlink
304 distclean : force_do_it
305 $perl $Build distclean
306 $unlink
307
308
309 force_do_it :
310 @ $noop
311 EOF
312 $action : force_do_it
313 $perl $Build $action
314 EOF
315 MODULE_BUILD_COMPAT
316
317 $fatpacked{"Module/Build/Config.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_CONFIG';
318 package Module::Build::Config;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Config;sub new {my ($pack,%args)=@_;return bless {stack=>{},values=>$args{values}|| {},},$pack}sub get {my ($self,$key)=@_;return$self->{values}{$key}if ref($self)&& exists$self->{values}{$key};return$Config{$key}}sub set {my ($self,$key,$val)=@_;$self->{values}{$key}=$val}sub push {my ($self,$key,$val)=@_;push @{$self->{stack}{$key}},$self->{values}{$key}if exists$self->{values}{$key};$self->{values}{$key}=$val}sub pop {my ($self,$key)=@_;my$val=delete$self->{values}{$key};if (exists$self->{stack}{$key}){$self->{values}{$key}=pop @{$self->{stack}{$key}};delete$self->{stack}{$key}unless @{$self->{stack}{$key}}}return$val}sub values_set {my$self=shift;return undef unless ref($self);return$self->{values}}sub all_config {my$self=shift;my$v=ref($self)? $self->{values}: {};return {%Config,%$v}}1;
319 MODULE_BUILD_CONFIG
320
321 $fatpacked{"Module/Build/ConfigData.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_CONFIGDATA';
322 package Module::Build::ConfigData;use strict;my$arrayref=eval do {local $/;<DATA>}or die "Couldn't load ConfigData data: $@";close DATA;my ($config,$features,$auto_features)=@$arrayref;sub config {$config->{$_[1]}}sub set_config {$config->{$_[1]}=$_[2]}sub set_feature {$features->{$_[1]}=0+!!$_[2]}sub auto_feature_names {sort grep!exists$features->{$_},keys %$auto_features}sub feature_names {my@features=(sort keys %$features,auto_feature_names());@features}sub config_names {sort keys %$config}sub write {my$me=__FILE__;require Data::Dumper;my$mode_orig=(stat$me)[2]& 07777;chmod($mode_orig | 0222,$me);open(my$fh,'+<',$me)or die "Can't rewrite $me: $!";seek($fh,0,0);while (<$fh>){last if /^__DATA__$/}die "Couldn't find __DATA__ token in $me" if eof($fh);seek($fh,tell($fh),0);my$data=[$config,$features,$auto_features];print($fh 'do{ my ' .Data::Dumper->new([$data],['x'])->Purity(1)->Dump().'$x; }');truncate($fh,tell($fh));close$fh;chmod($mode_orig,$me)or warn "Couldn't restore permissions on $me: $!"}sub feature {my ($package,$key)=@_;return$features->{$key}if exists$features->{$key};my$info=$auto_features->{$key}or return 0;require Module::Build;for my$type (sort keys %$info){my$prereqs=$info->{$type};next if$type eq 'description' || $type eq 'recommends';for my$modname (sort keys %$prereqs){my$status=Module::Build->check_installed_status($modname,$prereqs->{$modname});if ((!$status->{ok})xor ($type =~ /conflicts$/)){return 0}if (!eval "require $modname; 1"){return 0}}}return 1}__DATA__ do{ my $x = [
323 {},
324 {},
325 {
326 'HTML_support' => {
327 'description' => 'Create HTML documentation',
328 'requires' => {
329 'Pod::Html' => 0
330 }
331 },
332 'PPM_support' => {
333 'description' => 'Generate PPM files for distributions'
334 },
335 'dist_authoring' => {
336 'description' => 'Create new distributions',
337 'recommends' => {
338 'Module::Signature' => '0.21',
339 'Pod::Readme' => '0.04'
340 },
341 'requires' => {
342 'Archive::Tar' => '1.09'
343 }
344 },
345 'inc_bundling_support' => {
346 'description' => 'Bundle Module::Build in inc/',
347 'requires' => {
348 'ExtUtils::Install' => '1.54',
349 'ExtUtils::Installed' => '1.999',
350 'inc::latest' => '0.5'
351 }
352 },
353 'license_creation' => {
354 'description' => 'Create licenses automatically in distributions',
355 'requires' => {
356 'Software::License' => '0.103009'
357 }
358 },
359 'manpage_support' => {
360 'description' => 'Create Unix man pages',
361 'requires' => {
362 'Pod::Man' => 0
363 }
364 }
365 }
366 ];
367 $x; }
368 MODULE_BUILD_CONFIGDATA
369
370 $fatpacked{"Module/Build/Cookbook.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_COOKBOOK';
371 package Module::Build::Cookbook;use strict;use warnings;our$VERSION='0.4224';
372 MODULE_BUILD_COOKBOOK
373
374 $fatpacked{"Module/Build/Dumper.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_DUMPER';
375 package Module::Build::Dumper;use strict;use warnings;our$VERSION='0.4224';use Data::Dumper;sub _data_dump {my ($self,$data)=@_;return ("do{ my " .Data::Dumper->new([$data],['x'])->Purity(1)->Terse(0)->Sortkeys(1)->Dump().'$x; }')}1;
376 MODULE_BUILD_DUMPER
377
378 $fatpacked{"Module/Build/Notes.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_NOTES';
379 package Module::Build::Notes;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Data::Dumper;use Module::Build::Dumper;sub new {my ($class,%args)=@_;my$file=delete$args{file}or die "Missing required parameter 'file' to new()";my$self=bless {disk=>{},new=>{},file=>$file,%args,},$class}sub restore {my$self=shift;open(my$fh,'<',$self->{file})or die "Can't read $self->{file}: $!";$self->{disk}=eval do {local $/;<$fh>};die $@ if $@;close$fh;$self->{new}={}}sub access {my$self=shift;return$self->read()unless @_;my$key=shift;return$self->read($key)unless @_;my$value=shift;$self->write({$key=>$value });return$self->read($key)}sub has_data {my$self=shift;return keys %{$self->read()}> 0}sub exists {my ($self,$key)=@_;return exists($self->{new}{$key})|| exists($self->{disk}{$key})}sub read {my$self=shift;if (@_){my$key=shift;return$self->{new}{$key}if exists$self->{new}{$key};return$self->{disk}{$key}}my$out=(keys %{$self->{new}}? {%{$self->{disk}},%{$self->{new}}}: $self->{disk});return wantarray ? %$out : $out}sub _same {my ($self,$x,$y)=@_;return 1 if!defined($x)and!defined($y);return 0 if!defined($x)or!defined($y);return$x eq $y}sub write {my ($self,$href)=@_;$href ||= {};@{$self->{new}}{keys %$href }=values %$href;for my$key (keys %{$self->{new}}){next if ref$self->{new}{$key};next if ref$self->{disk}{$key}or!exists$self->{disk}{$key};delete$self->{new}{$key}if$self->_same($self->{new}{$key},$self->{disk}{$key})}if (my$file=$self->{file}){my ($vol,$dir,$base)=File::Spec->splitpath($file);$dir=File::Spec->catpath($vol,$dir,'');return unless -e $dir && -d $dir;return if -e $file and!keys %{$self->{new}};@{$self->{disk}}{keys %{$self->{new}}}=values %{$self->{new}};$self->_dump($file,$self->{disk});$self->{new}={}}return$self->read}sub _dump {my ($self,$file,$data)=@_;open(my$fh,'>',$file)or die "Can't create '$file': $!";print {$fh}Module::Build::Dumper->_data_dump($data);close$fh}my$orig_template=do {local $/;<DATA>};close DATA;sub write_config_data {my ($self,%args)=@_;my$template=$orig_template;$template =~ s/NOTES_NAME/$args{config_module}/g;$template =~ s/MODULE_NAME/$args{module}/g;$template =~ s/=begin private\n//;$template =~ s/=end private/=cut/;$template =~ s{$_\n}{} for '=begin private','=end private';open(my$fh,'>',$args{file})or die "Can't create '$args{file}': $!";print {$fh}$template;print {$fh}"\n__DATA__\n";print {$fh}Module::Build::Dumper->_data_dump([$args{config_data},$args{feature},$args{auto_features}]);close$fh}1;__DATA__ package NOTES_NAME;
380 use strict;
381 my $arrayref = eval do {local $/; <DATA>}
382 or die "Couldn't load ConfigData data: $@";
383 close DATA;
384 my ($config, $features, $auto_features) = @$arrayref;
385
386 sub config { $config->{$_[1]} }
387
388 sub set_config { $config->{$_[1]} = $_[2] }
389 sub set_feature { $features->{$_[1]} = 0+!!$_[2] } # Constrain to 1 or 0
390
391 sub auto_feature_names { sort grep !exists $features->{$_}, keys %$auto_features }
392
393 sub feature_names {
394 my @features = (sort keys %$features, auto_feature_names());
395 @features;
396 }
397
398 sub config_names { sort keys %$config }
399
400 sub write {
401 my $me = __FILE__;
402
403 # Can't use Module::Build::Dumper here because M::B is only a
404 # build-time prereq of this module
405 require Data::Dumper;
406
407 my $mode_orig = (stat $me)[2] & 07777;
408 chmod($mode_orig | 0222, $me); # Make it writeable
409 open(my $fh, '+<', $me) or die "Can't rewrite $me: $!";
410 seek($fh, 0, 0);
411 while (<$fh>) {
412 last if /^__DATA__$/;
413 }
414 die "Couldn't find __DATA__ token in $me" if eof($fh);
415
416 seek($fh, tell($fh), 0);
417 my $data = [$config, $features, $auto_features];
418 print($fh 'do{ my '
419 . Data::Dumper->new([$data],['x'])->Purity(1)->Dump()
420 . '$x; }' );
421 truncate($fh, tell($fh));
422 close $fh;
423
424 chmod($mode_orig, $me)
425 or warn "Couldn't restore permissions on $me: $!";
426 }
427
428 sub feature {
429 my ($package, $key) = @_;
430 return $features->{$key} if exists $features->{$key};
431
432 my $info = $auto_features->{$key} or return 0;
433
434 require Module::Build; # XXX should get rid of this
435 foreach my $type (sort keys %$info) {
436 my $prereqs = $info->{$type};
437 next if $type eq 'description' || $type eq 'recommends';
438
439 foreach my $modname (sort keys %$prereqs) {
440 my $status = Module::Build->check_installed_status($modname, $prereqs->{$modname});
441 if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; }
442 if ( ! eval "require $modname; 1" ) { return 0; }
443 }
444 }
445 return 1;
446 }
447
448 =begin private
449
450 =head1 NAME
451
452 NOTES_NAME - Configuration for MODULE_NAME
453
454 =head1 SYNOPSIS
455
456 use NOTES_NAME;
457 $value = NOTES_NAME->config('foo');
458 $value = NOTES_NAME->feature('bar');
459
460 @names = NOTES_NAME->config_names;
461 @names = NOTES_NAME->feature_names;
462
463 NOTES_NAME->set_config(foo => $new_value);
464 NOTES_NAME->set_feature(bar => $new_value);
465 NOTES_NAME->write; # Save changes
466
467
468 =head1 DESCRIPTION
469
470 This module holds the configuration data for the C<MODULE_NAME>
471 module. It also provides a programmatic interface for getting or
472 setting that configuration data. Note that in order to actually make
473 changes, you'll have to have write access to the C<NOTES_NAME>
474 module, and you should attempt to understand the repercussions of your
475 actions.
476
477
478 =head1 METHODS
479
480 =over 4
481
482 =item config($name)
483
484 Given a string argument, returns the value of the configuration item
485 by that name, or C<undef> if no such item exists.
486
487 =item feature($name)
488
489 Given a string argument, returns the value of the feature by that
490 name, or C<undef> if no such feature exists.
491
492 =item set_config($name, $value)
493
494 Sets the configuration item with the given name to the given value.
495 The value may be any Perl scalar that will serialize correctly using
496 C<Data::Dumper>. This includes references, objects (usually), and
497 complex data structures. It probably does not include transient
498 things like filehandles or sockets.
499
500 =item set_feature($name, $value)
501
502 Sets the feature with the given name to the given boolean value. The
503 value will be converted to 0 or 1 automatically.
504
505 =item config_names()
506
507 Returns a list of all the names of config items currently defined in
508 C<NOTES_NAME>, or in scalar context the number of items.
509
510 =item feature_names()
511
512 Returns a list of all the names of features currently defined in
513 C<NOTES_NAME>, or in scalar context the number of features.
514
515 =item auto_feature_names()
516
517 Returns a list of all the names of features whose availability is
518 dynamically determined, or in scalar context the number of such
519 features. Does not include such features that have later been set to
520 a fixed value.
521
522 =item write()
523
524 Commits any changes from C<set_config()> and C<set_feature()> to disk.
525 Requires write access to the C<NOTES_NAME> module.
526
527 =back
528
529
530 =head1 AUTHOR
531
532 C<NOTES_NAME> was automatically created using C<Module::Build>.
533 C<Module::Build> was written by Ken Williams, but he holds no
534 authorship claim or copyright claim to the contents of C<NOTES_NAME>.
535
536 =end private
537
538 MODULE_BUILD_NOTES
539
540 $fatpacked{"Module/Build/PPMMaker.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PPMMAKER';
541 package Module::Build::PPMMaker;use strict;use warnings;use Config;our$VERSION='0.4224';$VERSION=eval$VERSION;sub new {my$package=shift;return bless {@_},$package}sub make_ppd {my ($self,%args)=@_;my$build=delete$args{build};my@codebase;if (exists$args{codebase}){@codebase=ref$args{codebase}? @{$args{codebase}}: ($args{codebase})}else {my$distfile=$build->ppm_name .'.tar.gz';print "Using default codebase '$distfile'\n";@codebase=($distfile)}my%dist;for my$info (qw(name author abstract version)){my$method="dist_$info";$dist{$info}=$build->$method()or die "Can't determine distribution's $info\n"}$self->_simple_xml_escape($_)foreach$dist{abstract},@{$dist{author}};my$ppd=<<"PPD";for my$type (qw(requires)){my$prereq=$build->$type();for my$modname (sort keys %$prereq){next if$modname eq 'perl';my$min_version='0.0';for my$c ($build->_parse_conditions($prereq->{$modname})){my ($op,$version)=$c =~ /^\s* (<=?|>=?|==|!=) \s* ([\w.]+) \s*$/x;if ($op eq '>='){$min_version=$version;last}}$modname .= '::' unless$modname =~ /::/;$ppd .= qq! <REQUIRE NAME="$modname" VERSION="$min_version" />\n!}}if (keys %{$build->find_xs_files}){my$perl_version=$self->_ppd_version($build->perl_version);$ppd .= sprintf(<<'EOF',$self->_varchname($build->config))}for my$codebase (@codebase){$self->_simple_xml_escape($codebase);$ppd .= sprintf(<<'EOF',$codebase)}$ppd .= <<'EOF';my$ppd_file="$dist{name}.ppd";open(my$fh,'>',$ppd_file)or die "Cannot write to $ppd_file: $!";binmode($fh,":utf8")if $] >= 5.008 && $Config{useperlio};print$fh $ppd;close$fh;return$ppd_file}sub _ppd_version {my ($self,$version)=@_;return join ',',(split(/\./,$version),(0)x4)[0..3]}sub _varchname {my ($self,$config)=@_;my$varchname=$config->{archname};if ($] >= 5.008){my$vstring=sprintf "%vd",$^V;$vstring =~ s/\.\d+$//;$varchname .= "-$vstring"}return$varchname}{my%escapes=("\n"=>"\\n",'"'=>'&quot;','&'=>'&amp;','>'=>'&gt;','<'=>'&lt;',);my$rx=join '|',keys%escapes;sub _simple_xml_escape {$_[1]=~ s/($rx)/$escapes{$1}/go}}1;
542 <SOFTPKG NAME=\"$dist{name}\" VERSION=\"$dist{version}\">
543 <ABSTRACT>$dist{abstract}</ABSTRACT>
544 @{[ join "\n", map " <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
545 <IMPLEMENTATION>
546 PPD
547 <ARCHITECTURE NAME="%s" />
548 EOF
549 <CODEBASE HREF="%s" />
550 EOF
551 </IMPLEMENTATION>
552 </SOFTPKG>
553 EOF
554 MODULE_BUILD_PPMMAKER
555
556 $fatpacked{"Module/Build/Platform/Default.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_DEFAULT';
557 package Module::Build::Platform::Default;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Base;our@ISA=qw(Module::Build::Base);1;
558 MODULE_BUILD_PLATFORM_DEFAULT
559
560 $fatpacked{"Module/Build/Platform/MacOS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_MACOS';
561 package Module::Build::Platform::MacOS;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Base;our@ISA=qw(Module::Build::Base);use ExtUtils::Install;sub have_forkpipe {0}sub new {my$class=shift;my$self=$class->SUPER::new(@_);for ('sitelib','sitearch'){$self->config($_=>$self->config("install$_"))unless$self->config($_)}(my$sp=$self->config('startperl'))=~ s/.*Exit \{Status\}\s//;$self->config(startperl=>$sp);return$self}sub make_executable {my$self=shift;require MacPerl;for (@_){MacPerl::SetFileInfo('McPL','TEXT',$_)}}sub dispatch {my$self=shift;if(!@_ and!@ARGV){require MacPerl;my@action_list=qw(build test install);my%actions=map {+($_,1)}$self->known_actions;delete@actions{@action_list};push@action_list,sort {$a cmp $b}keys%actions;my%toolserver=map {+$_=>1}qw(test disttest diff testdb);for (@action_list){$_ .= ' *' if$toolserver{$_}}my$cmd=MacPerl::Pick("What build command? ('*' requires ToolServer)",@action_list);return unless defined$cmd;$cmd =~ s/ \*$//;$ARGV[0]=($cmd);my$args=MacPerl::Ask('Any extra arguments? (ie. verbose=1)','');return unless defined$args;push@ARGV,$self->split_like_shell($args)}$self->SUPER::dispatch(@_)}sub ACTION_realclean {my$self=shift;chmod 0666,$self->{properties}{build_script};$self->SUPER::ACTION_realclean}sub ACTION_install {my$self=shift;return$self->SUPER::ACTION_install(@_)if eval {ExtUtils::Install->VERSION('1.30');1};local $^W=0;local*ExtUtils::Install::find=sub {my ($code,@dirs)=@_;@dirs=map {$_ eq '.' ? File::Spec->curdir : $_}@dirs;return File::Find::find($code,@dirs)};return$self->SUPER::ACTION_install(@_)}1;
562 MODULE_BUILD_PLATFORM_MACOS
563
564 $fatpacked{"Module/Build/Platform/Unix.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_UNIX';
565 package Module::Build::Platform::Unix;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Base;our@ISA=qw(Module::Build::Base);sub is_executable {my ($self,$file)=@_;return +(stat$file)[2]& 0100}sub _startperl {"#! " .shift()->perl}sub _construct {my$self=shift()->SUPER::_construct(@_);my$c=$self->{config};for (qw(siteman1 siteman3 vendorman1 vendorman3)){$c->{"install${_}dir"}||= $c->{"install${_}"}}return$self}sub _detildefy {my ($self,$value)=@_;$value =~ s[^~([^/]+)?(?=/|$)] # tilde with optional username [$1 ? (eval{(getpwnam $1)[7]}|| "~$1"): ($ENV{HOME}|| eval{(getpwuid $>)[7]}|| glob("~"))]ex;return$value}1;
566 MODULE_BUILD_PLATFORM_UNIX
567
568 $fatpacked{"Module/Build/Platform/VMS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_VMS';
569 package Module::Build::Platform::VMS;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Base;use Config;our@ISA=qw(Module::Build::Base);sub _set_defaults {my$self=shift;$self->SUPER::_set_defaults(@_);$self->{properties}{build_script}='Build.com'}sub cull_args {my$self=shift;my($action,$args)=$self->SUPER::cull_args(@_);my@possible_actions=grep {lc $_ eq lc$action}$self->known_actions;die "Ambiguous action '$action'. Could be one of @possible_actions" if@possible_actions > 1;return ($possible_actions[0],$args)}sub manpage_separator {return '__'}sub _catprefix {my($self,$rprefix,$default)=@_;my($rvol,$rdirs)=File::Spec->splitpath($rprefix);if($rvol){return File::Spec->catpath($rvol,File::Spec->catdir($rdirs,$default),'')}else {return File::Spec->catdir($rdirs,$default)}}sub _prefixify {my($self,$path,$sprefix,$type)=@_;my$rprefix=$self->prefix;return '' unless defined$path;$self->log_verbose(" prefixify $path from $sprefix to $rprefix\n");$rprefix=VMS::Filespec::vmspath($rprefix)if$rprefix;$sprefix=VMS::Filespec::vmspath($sprefix)if$sprefix;$self->log_verbose(" rprefix translated to $rprefix\n"." sprefix translated to $sprefix\n");if(length($path)==0){$self->log_verbose(" no path to prefixify.\n")}elsif(!File::Spec->file_name_is_absolute($path)){$self->log_verbose(" path is relative, not prefixifying.\n")}elsif($sprefix eq $rprefix){$self->log_verbose(" no new prefix.\n")}else {my($path_vol,$path_dirs)=File::Spec->splitpath($path);my$vms_prefix=$self->config('vms_prefix');if($path_vol eq $vms_prefix.':'){$self->log_verbose(" $vms_prefix: seen\n");$path_dirs =~ s{^\[}{\[.} unless$path_dirs =~ m{^\[\.};$path=$self->_catprefix($rprefix,$path_dirs)}else {$self->log_verbose(" cannot prefixify.\n");return$self->prefix_relpaths($self->installdirs,$type)}}$self->log_verbose(" now $path\n");return$path}sub _quote_args {my ($self,@args)=@_;my$got_arrayref=(scalar(@args)==1 && ref$args[0]eq 'ARRAY')? 1 : 0;map {if (!/^\//){$_ =~ s/\"/""/g;$_=q(").$_.q(")}}($got_arrayref ? @{$args[0]}: @args);return$got_arrayref ? $args[0]: join(' ',@args)}sub have_forkpipe {0}sub _backticks {my ($self,@cmd)=@_;my$cmd=shift@cmd;my$args=$self->_quote_args(@cmd);return `$cmd $args`}sub find_command {my ($self,$command)=@_;if ($^O eq 'VMS'){require VMS::DCLsym;my$syms=VMS::DCLsym->new;return$command if scalar$syms->getsym(uc$command)}$self->SUPER::find_command($command)}sub _maybe_command {my($self,$file)=@_;return$file if -x $file &&!-d _;my(@dirs)=('');my(@exts)=('',$Config{'exe_ext'},'.exe','.com');if ($file !~ m![/:>\]]!){for (my$i=0;defined$ENV{"DCL\$PATH;$i"};$i++){my$dir=$ENV{"DCL\$PATH;$i"};$dir .= ':' unless$dir =~ m%[\]:]$%;push(@dirs,$dir)}push(@dirs,'Sys$System:');for my$dir (@dirs){my$sysfile="$dir$file";for my$ext (@exts){return$file if -x "$sysfile$ext" &&!-d _}}}return}sub do_system {my ($self,@cmd)=@_;$self->log_verbose("@cmd\n");my$cmd=shift@cmd;my$args=$self->_quote_args(@cmd);return!system("$cmd $args")}sub oneliner {my$self=shift;my$oneliner=$self->SUPER::oneliner(@_);$oneliner =~ s/^\"\S+\"//;return "MCR $^X $oneliner"}sub rscan_dir {my ($self,$dir,$pattern)=@_;my$result=$self->SUPER::rscan_dir($dir,$pattern);for my$file (@$result){if (!_efs()&& ($file =~ m#/#)){$file =~ s/\.$//}}return$result}sub dist_dir {my$self=shift;my$dist_dir=$self->SUPER::dist_dir;$dist_dir =~ s/\./_/g unless _efs();return$dist_dir}sub man3page_name {my$self=shift;my$mpname=$self->SUPER::man3page_name(shift);my$sep=$self->manpage_separator;$mpname =~ s/^$sep//;return$mpname}sub expand_test_dir {my ($self,$dir)=@_;my@reldirs=$self->SUPER::expand_test_dir($dir);for my$eachdir (@reldirs){my ($v,$d,$f)=File::Spec->splitpath($eachdir);my$reldir=File::Spec->abs2rel(File::Spec->catpath($v,$d,''));$eachdir=File::Spec->catfile($reldir,$f)}return@reldirs}sub _detildefy {my ($self,$arg)=@_;return$arg if ($arg =~ /^~~/);return$arg if ($arg =~ /^~ /);if ($arg =~ /^~/){my$spec=$arg;$spec =~ s/^~//;$spec =~ s#^/##;my$home=VMS::Filespec::unixify($ENV{HOME});$home .= '/' unless$home =~ m#/$#;if ($spec eq ''){$home =~ s#/$##;return$home}my ($hvol,$hdir,$hfile)=File::Spec::Unix->splitpath($home);if ($hdir eq ''){$hdir=$hfile}my ($vol,$dir,$file)=File::Spec::Unix->splitpath($spec);my@hdirs=File::Spec::Unix->splitdir($hdir);my@dirs=File::Spec::Unix->splitdir($dir);unless ($arg =~ m#^~/#){shift@dirs}my$newdirs=File::Spec::Unix->catdir(@hdirs,@dirs);$arg=File::Spec::Unix->catpath($hvol,$newdirs,$file)}return$arg}sub find_perl_interpreter {return VMS::Filespec::vmsify($^X)}sub localize_file_path {my ($self,$path)=@_;$path=VMS::Filespec::vmsify($path);$path =~ s/\.\z//;return$path}sub localize_dir_path {my ($self,$path)=@_;return VMS::Filespec::vmspath($path)}sub ACTION_clean {my ($self)=@_;for my$item (map glob(VMS::Filespec::rmsexpand($_,'.;0')),$self->cleanup){$self->delete_filetree($item)}}my$use_feature;BEGIN {if (eval {local$SIG{__DIE__};require VMS::Feature}){$use_feature=1}}sub _unix_rpt {my$unix_rpt;if ($use_feature){$unix_rpt=VMS::Feature::current("filename_unix_report")}else {my$env_unix_rpt=$ENV{'DECC$FILENAME_UNIX_REPORT'}|| '';$unix_rpt=$env_unix_rpt =~ /^[ET1]/i}return$unix_rpt}sub _efs {my$efs;if ($use_feature){$efs=VMS::Feature::current("efs_charset")}else {my$env_efs=$ENV{'DECC$EFS_CHARSET'}|| '';$efs=$env_efs =~ /^[ET1]/i}return$efs}1;
570 MODULE_BUILD_PLATFORM_VMS
571
572 $fatpacked{"Module/Build/Platform/VOS.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_VOS';
573 package Module::Build::Platform::VOS;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Base;our@ISA=qw(Module::Build::Base);1;
574 MODULE_BUILD_PLATFORM_VOS
575
576 $fatpacked{"Module/Build/Platform/Windows.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_WINDOWS';
577 package Module::Build::Platform::Windows;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Config;use File::Basename;use File::Spec;use Module::Build::Base;our@ISA=qw(Module::Build::Base);sub manpage_separator {return '.'}sub have_forkpipe {0}sub _detildefy {my ($self,$value)=@_;$value =~ s,^~(?= [/\\] | $ ),$ENV{HOME},x if$ENV{HOME};return$value}sub ACTION_realclean {my ($self)=@_;$self->SUPER::ACTION_realclean();my$basename=basename($0);$basename =~ s/(?:\.bat)?$//i;if (lc$basename eq lc$self->build_script){if ($self->build_bat){$self->log_verbose("Deleting $basename.bat\n");my$full_progname=$0;$full_progname =~ s/(?:\.bat)?$/.bat/i;require Win32;my$null_arg=(Win32::IsWinNT())? '""' : '';my$cmd=qq(start $null_arg /min "\%comspec\%" /c del "$full_progname");open(my$fh,'>>',"$basename.bat")or die "Can't create $basename.bat: $!";print$fh $cmd;close$fh }else {$self->delete_filetree($self->build_script .'.bat')}}}sub make_executable {my$self=shift;$self->SUPER::make_executable(@_);for my$script (@_){if ($script =~ /\.(bat|cmd)$/){$self->SUPER::make_executable($script);next}else {my%opts=();if ($script eq $self->build_script){$opts{ntargs}=q(-x -S %0 --build_bat %*);$opts{otherargs}=q(-x -S "%0" --build_bat %1 %2 %3 %4 %5 %6 %7 %8 %9)}my$out=eval {$self->pl2bat(in=>$script,update=>1,%opts)};if ($@){$self->log_warn("WARNING: Unable to convert file '$script' to an executable script:\n$@")}else {$self->SUPER::make_executable($out)}}}}sub pl2bat {my$self=shift;my%opts=@_;$opts{ntargs}='-x -S %0 %*' unless exists$opts{ntargs};$opts{otherargs}='-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9' unless exists$opts{otherargs};$opts{stripsuffix}='/\\.plx?/' unless exists$opts{stripsuffix};$opts{stripsuffix}=($opts{stripsuffix}=~ m{^/([^/]*[^/\$]|)\$?/?$} ? $1 : "\Q$opts{stripsuffix}\E");unless (exists$opts{out}){$opts{out}=$opts{in};$opts{out}=~ s/$opts{stripsuffix}$//oi;$opts{out}.= '.bat' unless$opts{in}=~ /\.bat$/i or $opts{in}=~ /^-$/}my$head=<<EOT;$head =~ s/^\s+//gm;my$headlines=2 + ($head =~ tr/\n/\n/);my$tail="\n__END__\n:endofperl\n";my$linedone=0;my$taildone=0;my$linenum=0;my$skiplines=0;my$start=$Config{startperl};$start="#!perl" unless$start =~ /^#!.*perl/;open(my$in,'<',"$opts{in}")or die "Can't open $opts{in}: $!";my@file=<$in>;close($in);for my$line (@file){$linenum++;if ($line =~ /^:endofperl\b/){if (!exists$opts{update}){warn "$opts{in} has already been converted to a batch file!\n";return}$taildone++}if (not $linedone and $line =~ /^#!.*perl/){if (exists$opts{update}){$skiplines=$linenum - 1;$line .= "#line ".(1+$headlines)."\n"}else {$line .= "#line ".($linenum+$headlines)."\n"}$linedone++}if ($line =~ /^#\s*line\b/ and $linenum==2 + $skiplines){$line=""}}open(my$out,'>',"$opts{out}")or die "Can't open $opts{out}: $!";print$out $head;print$out $start,($opts{usewarnings}? " -w" : ""),"\n#line ",($headlines+1),"\n" unless$linedone;print$out @file[$skiplines..$#file];print$out $tail unless$taildone;close($out);return$opts{out}}sub _quote_args {my ($self,@args)=@_;my@quoted;for (@args){if (/^[^\s*?!\$<>;|'"\[\]\{\}]+$/){push@quoted,$_}else {s/"/\\"/g;push@quoted,qq("$_")}}return join " ",@quoted}sub split_like_shell {(my$self,local $_)=@_;return @$_ if defined()&& ref()eq 'ARRAY';my@argv;return@argv unless defined()&& length();my$length=length;m/\G\s*/gc;ARGS: until (pos==$length){my$quote_mode;my$arg='';CHARS: until (pos==$length){if (m/\G((?:\\\\)+)(?=\\?(")?)/gc){if (defined $2){$arg .= '\\' x (length($1)/ 2)}else {$arg .= $1}}elsif (m/\G\\"/gc){$arg .= '"'}elsif (m/\G"/gc){if ($quote_mode && m/\G"/gc){$arg .= '"'}$quote_mode=!$quote_mode}elsif (!$quote_mode && m/\G\s+/gc){last}elsif (m/\G(.)/sgc){$arg .= $1}}push@argv,$arg}return@argv}sub do_system {my ($self,@cmd)=@_;my$cmd=$self->_quote_args(@cmd);my$status=system($cmd);if ($status and $! =~ /Argument list too long/i){my$env_entries='';for (sort keys%ENV){$env_entries .= "$_=>".length($ENV{$_})."; "}warn "'Argument list' was 'too long', env lengths are $env_entries"}return!$status}sub _maybe_command {my($self,$file)=@_;my@e=exists($ENV{'PATHEXT'})? split(/;/,$ENV{PATHEXT}): qw(.com .exe .bat .cmd);my$e='';for (@e){$e .= "\Q$_\E|"}chop$e;if ($file =~ /($e)$/i){return$file if -e $file}else {for (@e){return "$file$_" if -e "$file$_"}}return}1;
578 \@rem = '--*-Perl-*--
579 \@echo off
580 if "%OS%" == "Windows_NT" goto WinNT
581 perl $opts{otherargs}
582 goto endofperl
583 :WinNT
584 perl $opts{ntargs}
585 if NOT "%COMSPEC%" == "%SystemRoot%\\system32\\cmd.exe" goto endofperl
586 if %errorlevel% == 9009 echo You do not have Perl in your PATH.
587 if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
588 goto endofperl
589 \@rem ';
590 EOT
591 MODULE_BUILD_PLATFORM_WINDOWS
592
593 $fatpacked{"Module/Build/Platform/aix.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_AIX';
594 package Module::Build::Platform::aix;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Platform::Unix;our@ISA=qw(Module::Build::Platform::Unix);1;
595 MODULE_BUILD_PLATFORM_AIX
596
597 $fatpacked{"Module/Build/Platform/cygwin.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_CYGWIN';
598 package Module::Build::Platform::cygwin;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Platform::Unix;our@ISA=qw(Module::Build::Platform::Unix);sub manpage_separator {'.'}sub _maybe_command {my ($self,$file)=@_;if ($file =~ m{^/cygdrive/}i){require Module::Build::Platform::Windows;return Module::Build::Platform::Windows->_maybe_command($file)}return$self->SUPER::_maybe_command($file)}1;
599 MODULE_BUILD_PLATFORM_CYGWIN
600
601 $fatpacked{"Module/Build/Platform/darwin.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_DARWIN';
602 package Module::Build::Platform::darwin;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Platform::Unix;our@ISA=qw(Module::Build::Platform::Unix);1;
603 MODULE_BUILD_PLATFORM_DARWIN
604
605 $fatpacked{"Module/Build/Platform/os2.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PLATFORM_OS2';
606 package Module::Build::Platform::os2;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;use Module::Build::Platform::Unix;our@ISA=qw(Module::Build::Platform::Unix);sub manpage_separator {'.'}sub have_forkpipe {0}sub _maybe_command {my($self,$file)=@_;$file =~ s,[/\\]+,/,g;return$file if -x $file &&!-d _;return "$file.exe" if -x "$file.exe" &&!-d _;return "$file.cmd" if -x "$file.cmd" &&!-d _;return}1;
607 MODULE_BUILD_PLATFORM_OS2
608
609 $fatpacked{"Module/Build/PodParser.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_PODPARSER';
610 package Module::Build::PodParser;use strict;use warnings;our$VERSION='0.4224';$VERSION=eval$VERSION;sub new {my$package=shift;my$self;$self=bless {have_pod_parser=>0,@_},$package;unless ($self->{fh}){die "No 'file' or 'fh' parameter given" unless$self->{file};open($self->{fh},'<',$self->{file})or die "Couldn't open $self->{file}: $!"}return$self}sub parse_from_filehandle {my ($self,$fh)=@_;local $_;while (<$fh>){next unless /^=(?!cut)/ .. /^=cut/;last if ($self->{abstract})=/^ (?: [a-z_0-9:]+ | [BCIF] < [a-z_0-9:]+ > ) \s+ - \s+ (.*\S) /ix}my@author;while (<$fh>){next unless /^=head1\s+AUTHORS?/i ... /^=/;next if /^=/;push@author,$_ if /\@/}return unless@author;s/^\s+|\s+$//g foreach@author;$self->{author}=\@author;return}sub get_abstract {my$self=shift;return$self->{abstract}if defined$self->{abstract};$self->parse_from_filehandle($self->{fh});return$self->{abstract}}sub get_author {my$self=shift;return$self->{author}if defined$self->{author};$self->parse_from_filehandle($self->{fh});return$self->{author}|| []}
611 MODULE_BUILD_PODPARSER
612
613 $fatpacked{"Module/Build/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'MODULE_BUILD_TINY';
614 package Module::Build::Tiny;$Module::Build::Tiny::VERSION='0.039';use strict;use warnings;use Exporter 5.57 'import';our@EXPORT=qw/Build Build_PL/;use CPAN::Meta;use ExtUtils::Config 0.003;use ExtUtils::Helpers 0.020 qw/make_executable split_like_shell man1_pagename man3_pagename detildefy/;use ExtUtils::Install qw/pm_to_blib install/;use ExtUtils::InstallPaths 0.002;use File::Basename qw/basename dirname/;use File::Find ();use File::Path qw/mkpath rmtree/;use File::Spec::Functions qw/catfile catdir rel2abs abs2rel splitdir curdir/;use Getopt::Long 2.36 qw/GetOptionsFromArray/;use JSON::PP 2 qw/encode_json decode_json/;sub write_file {my ($filename,$content)=@_;open my$fh,'>',$filename or die "Could not open $filename: $!\n";print$fh $content}sub read_file {my ($filename,$mode)=@_;open my$fh,'<',$filename or die "Could not open $filename: $!\n";return do {local $/;<$fh>}}sub get_meta {my ($metafile)=grep {-e $_}qw/META.json META.yml/ or die "No META information provided\n";return CPAN::Meta->load_file($metafile)}sub manify {my ($input_file,$output_file,$section,$opts)=@_;return if -e $output_file && -M $input_file <= -M $output_file;my$dirname=dirname($output_file);mkpath($dirname,$opts->{verbose})if not -d $dirname;require Pod::Man;Pod::Man->new(section=>$section)->parse_from_file($input_file,$output_file);print "Manifying $output_file\n" if$opts->{verbose}&& $opts->{verbose}> 0;return}sub process_xs {my ($source,$options)=@_;die "Can't build xs files under --pureperl-only\n" if$options->{'pureperl-only'};my (undef,@parts)=splitdir(dirname($source));push@parts,my$file_base=basename($source,'.xs');my$archdir=catdir(qw/blib arch auto/,@parts);my$tempdir='temp';my$c_file=catfile($tempdir,"$file_base.c");require ExtUtils::ParseXS;mkpath($tempdir,$options->{verbose},oct '755');ExtUtils::ParseXS::process_file(filename=>$source,prototypes=>0,output=>$c_file);my$version=$options->{meta}->version;require ExtUtils::CBuilder;my$builder=ExtUtils::CBuilder->new(config=>$options->{config}->values_set);my$ob_file=$builder->compile(source=>$c_file,defines=>{VERSION=>qq/"$version"/,XS_VERSION=>qq/"$version"/ },include_dirs=>[curdir,dirname($source)]);require DynaLoader;my$mod2fname=defined&DynaLoader::mod2fname ? \&DynaLoader::mod2fname : sub {return $_[0][-1]};mkpath($archdir,$options->{verbose},oct '755')unless -d $archdir;my$lib_file=catfile($archdir,$mod2fname->(\@parts).'.' .$options->{config}->get('dlext'));return$builder->link(objects=>$ob_file,lib_file=>$lib_file,module_name=>join '::',@parts)}sub find {my ($pattern,$dir)=@_;my@ret;File::Find::find(sub {push@ret,$File::Find::name if /$pattern/ && -f},$dir)if -d $dir;return@ret}my%actions=(build=>sub {my%opt=@_;for my$pl_file (find(qr/\.PL$/,'lib')){(my$pm=$pl_file)=~ s/\.PL$//;system $^X,$pl_file,$pm and die "$pl_file returned $?\n"}my%modules=map {$_=>catfile('blib',$_)}find(qr/\.p(?:m|od)$/,'lib');my%scripts=map {$_=>catfile('blib',$_)}find(qr//,'script');my%shared=map {$_=>catfile(qw/blib lib auto share dist/,$opt{meta}->name,abs2rel($_,'share'))}find(qr//,'share');pm_to_blib({%modules,%scripts,%shared},catdir(qw/blib lib auto/));make_executable($_)for values%scripts;mkpath(catdir(qw/blib arch/),$opt{verbose});process_xs($_,\%opt)for find(qr/.xs$/,'lib');if ($opt{install_paths}->install_destination('bindoc')&& $opt{install_paths}->is_default_installable('bindoc')){manify($_,catfile('blib','bindoc',man1_pagename($_)),$opt{config}->get('man1ext'),\%opt)for keys%scripts}if ($opt{install_paths}->install_destination('libdoc')&& $opt{install_paths}->is_default_installable('libdoc')){manify($_,catfile('blib','libdoc',man3_pagename($_)),$opt{config}->get('man3ext'),\%opt)for keys%modules}},test=>sub {my%opt=@_;die "Must run `./Build build` first\n" if not -d 'blib';require TAP::Harness::Env;my%test_args=((verbosity=>$opt{verbose})x!!exists$opt{verbose},(jobs=>$opt{jobs})x!!exists$opt{jobs},(color=>1)x!!-t STDOUT,lib=>[map {rel2abs(catdir(qw/blib/,$_))}qw/arch lib/ ],);my$tester=TAP::Harness::Env->create(\%test_args);$tester->runtests(sort +find(qr/\.t$/,'t'))->has_errors and exit 1},install=>sub {my%opt=@_;die "Must run `./Build build` first\n" if not -d 'blib';install($opt{install_paths}->install_map,@opt{qw/verbose dry_run uninst/})},clean=>sub {my%opt=@_;rmtree($_,$opt{verbose})for qw/blib temp/},realclean=>sub {my%opt=@_;rmtree($_,$opt{verbose})for qw/blib temp Build _build_params MYMETA.yml MYMETA.json/},);sub Build {my$action=@ARGV && $ARGV[0]=~ /\A\w+\z/ ? shift@ARGV : 'build';die "No such action '$action'\n" if not $actions{$action};my($env,$bargv)=@{decode_json(read_file('_build_params'))};my%opt;GetOptionsFromArray($_,\%opt,qw/install_base=s install_path=s% installdirs=s destdir=s prefix=s config=s% uninst:1 verbose:1 dry_run:1 pureperl-only:1 create_packlist=i jobs=i/)for ($env,$bargv,\@ARGV);$_=detildefy($_)for grep {defined}@opt{qw/install_base destdir prefix/},values %{$opt{install_path}};@opt{'config','meta' }=(ExtUtils::Config->new($opt{config}),get_meta());$actions{$action}->(%opt,install_paths=>ExtUtils::InstallPaths->new(%opt,dist_name=>$opt{meta}->name))}sub Build_PL {my$meta=get_meta();printf "Creating new 'Build' script for '%s' version '%s'\n",$meta->name,$meta->version;my$dir=$meta->name eq 'Module-Build-Tiny' ? "use lib 'lib';" : '';write_file('Build',"#!perl\n$dir\nuse Module::Build::Tiny;\nBuild();\n");make_executable('Build');my@env=defined$ENV{PERL_MB_OPT}? split_like_shell($ENV{PERL_MB_OPT}): ();write_file('_build_params',encode_json([\@env,\@ARGV ]));$meta->save(@$_)for ['MYMETA.json'],['MYMETA.yml'=>{version=>1.4 }]}1;
615 MODULE_BUILD_TINY
616
617 $fatpacked{"PadWalker.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PADWALKER';
618 package PadWalker;use strict;use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);require Exporter;require DynaLoader;require 5.008;@ISA=qw(Exporter DynaLoader);@EXPORT_OK=qw(peek_my peek_our closed_over peek_sub var_name set_closed_over);%EXPORT_TAGS=(all=>\@EXPORT_OK);$VERSION='2.3';bootstrap PadWalker$VERSION;sub peek_my;sub peek_our;sub closed_over;sub peek_sub;sub var_name;1;
619 PADWALKER
620
621 $fatpacked{"Path/Tiny.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'PATH_TINY';
622 use 5.008001;use strict;use warnings;package Path::Tiny;our$VERSION='0.104';use Config;use Exporter 5.57 (qw/import/);use File::Spec 0.86 ();use Carp ();our@EXPORT=qw/path/;our@EXPORT_OK=qw/cwd rootdir tempfile tempdir/;use constant {PATH=>0,CANON=>1,VOL=>2,DIR=>3,FILE=>4,TEMP=>5,IS_BSD=>(scalar $^O =~ /bsd$/),IS_WIN32=>($^O eq 'MSWin32'),};use overload (q{""}=>sub {$_[0]->[PATH]},bool=>sub () {1},fallback=>1,);sub FREEZE {return $_[0]->[PATH]}sub THAW {return path($_[2])}{no warnings 'once';*TO_JSON=*FREEZE};my$HAS_UU;sub _check_UU {!!eval {require Unicode::UTF8;Unicode::UTF8->VERSION(0.58);1}}my$HAS_PU;sub _check_PU {!!eval {require PerlIO::utf8_strict;PerlIO::utf8_strict->VERSION(0.003);1}}my$HAS_FLOCK=$Config{d_flock}|| $Config{d_fcntl_can_lock}|| $Config{d_lockf};my$SLASH=qr{[\\/]};my$NOTSLASH=qr{[^\\/]};my$DRV_VOL=qr{[a-z]:}i;my$UNC_VOL=qr{$SLASH $SLASH $NOTSLASH+ $SLASH $NOTSLASH+}x;my$WIN32_ROOT=qr{(?: $UNC_VOL $SLASH | $DRV_VOL $SLASH | $SLASH )}x;sub _win32_vol {my ($path,$drv)=@_;require Cwd;my$dcwd=eval {Cwd::getdcwd($drv)};$dcwd="$drv" unless defined$dcwd && length$dcwd;$dcwd =~ s{$SLASH?$}{/};$path =~ s{^$DRV_VOL}{$dcwd};return$path}sub _is_root {return IS_WIN32()? ($_[0]=~ /^$WIN32_ROOT$/): ($_[0]eq '/')}BEGIN {*_same=IS_WIN32()? sub {lc($_[0])eq lc($_[1])}: sub {$_[0]eq $_[1]}}my%MODEBITS=(om=>0007,gm=>0070,um=>0700);{my$m=0;$MODEBITS{$_}=(1 << $m++)for qw/ox ow or gx gw gr ux uw ur/};sub _symbolic_chmod {my ($mode,$symbolic)=@_;for my$clause (split /,\s*/,$symbolic){if ($clause =~ m{\A([augo]+)([=+-])([rwx]+)\z}){my ($who,$action,$perms)=($1,$2,$3);$who =~ s/a/ugo/g;for my$w (split //,$who){my$p=0;$p |= $MODEBITS{"$w$_"}for split //,$perms;if ($action eq '='){$mode=($mode & ~$MODEBITS{"${w}m"})| $p}else {$mode=$action eq "+" ? ($mode | $p): ($mode & ~$p)}}}else {Carp::croak("Invalid mode clause '$clause' for chmod()")}}return$mode}{package flock;use if Path::Tiny::IS_BSD(),'warnings::register'}my$WARNED_BSD_NFS=0;sub _throw {my ($self,$function,$file,$msg)=@_;if (IS_BSD()&& $function =~ /^flock/ && $! =~ /operation not supported/i &&!warnings::fatal_enabled('flock')){if (!$WARNED_BSD_NFS){warnings::warn(flock=>"No flock for NFS on BSD: continuing in unsafe mode");$WARNED_BSD_NFS++}}else {$msg=$! unless defined$msg;Path::Tiny::Error->throw($function,(defined$file ? $file : $self->[PATH]),$msg)}return}sub _get_args {my ($raw,@valid)=@_;if (defined($raw)&& ref($raw)ne 'HASH'){my (undef,undef,undef,$called_as)=caller(1);$called_as =~ s{^.*::}{};Carp::croak("Options for $called_as must be a hash reference")}my$cooked={};for my$k (@valid){$cooked->{$k}=delete$raw->{$k}if exists$raw->{$k}}if (keys %$raw){my (undef,undef,undef,$called_as)=caller(1);$called_as =~ s{^.*::}{};Carp::croak("Invalid option(s) for $called_as: " .join(", ",keys %$raw))}return$cooked}sub path {my$path=shift;Carp::croak("Path::Tiny paths require defined, positive-length parts")unless 1 + @_==grep {defined && length}$path,@_;if (!@_ && ref($path)eq __PACKAGE__ &&!$path->[TEMP]){return$path}$path="$path";if (IS_WIN32()){$path=_win32_vol($path,$1)if$path =~ m{^($DRV_VOL)(?:$NOTSLASH|$)};$path .= "/" if$path =~ m{^$UNC_VOL$}}if (@_){$path .= (_is_root($path)? "" : "/").join("/",@_)}my$cpath=$path=File::Spec->canonpath($path);$path =~ tr[\\][/] if IS_WIN32();$path="/" if$path eq '/..';$path .= "/" if IS_WIN32()&& $path =~ m{^$UNC_VOL$};if (_is_root($path)){$path =~ s{/?$}{/}}else {$path =~ s{/$}{}}if ($path =~ m{^(~[^/]*).*}){require File::Glob;my ($homedir)=File::Glob::bsd_glob($1);$homedir =~ tr[\\][/] if IS_WIN32();$path =~ s{^(~[^/]*)}{$homedir}}bless [$path,$cpath ],__PACKAGE__}sub new {shift;path(@_)}sub cwd {require Cwd;return path(Cwd::getcwd())}sub rootdir {path(File::Spec->rootdir)}sub tempfile {shift if @_ && $_[0]eq 'Path::Tiny';my$opts=(@_ && ref $_[0]eq 'HASH')? shift @_ : {};$opts=_get_args($opts,qw/realpath/);my ($maybe_template,$args)=_parse_file_temp_args(@_);$args->{TEMPLATE}=$maybe_template->[0]if @$maybe_template;require File::Temp;my$temp=File::Temp->new(TMPDIR=>1,%$args);close$temp;my$self=$opts->{realpath}? path($temp)->realpath : path($temp)->absolute;$self->[TEMP]=$temp;return$self}sub tempdir {shift if @_ && $_[0]eq 'Path::Tiny';my$opts=(@_ && ref $_[0]eq 'HASH')? shift @_ : {};$opts=_get_args($opts,qw/realpath/);my ($maybe_template,$args)=_parse_file_temp_args(@_);require File::Temp;my$temp=File::Temp->newdir(@$maybe_template,TMPDIR=>1,%$args);my$self=$opts->{realpath}? path($temp)->realpath : path($temp)->absolute;$self->[TEMP]=$temp;$temp->{REALNAME}=$self->[CANON]if IS_WIN32;return$self}sub _parse_file_temp_args {my$leading_template=(scalar(@_)% 2==1 ? shift(@_): '');my%args=@_;%args=map {uc($_),$args{$_}}keys%args;my@template=(exists$args{TEMPLATE}? delete$args{TEMPLATE}: $leading_template ? $leading_template : ());return (\@template,\%args)}sub _splitpath {my ($self)=@_;@{$self}[VOL,DIR,FILE ]=File::Spec->splitpath($self->[PATH])}sub _resolve_symlinks {my ($self)=@_;my$new=$self;my ($count,%seen)=0;while (-l $new->[PATH]){if ($seen{$new->[PATH]}++){$self->_throw('readlink',$self->[PATH],"symlink loop detected")}if (++$count > 100){$self->_throw('readlink',$self->[PATH],"maximum symlink depth exceeded")}my$resolved=readlink$new->[PATH]or $new->_throw('readlink',$new->[PATH]);$resolved=path($resolved);$new=$resolved->is_absolute ? $resolved : $new->sibling($resolved)}return$new}sub absolute {my ($self,$base)=@_;if (IS_WIN32){return$self if length$self->volume;if ($self->is_absolute){require Cwd;my ($drv)=Win32::GetCwd()=~ /^($DRV_VOL | $UNC_VOL)/x;return path($drv .$self->[PATH])}}else {return$self if$self->is_absolute}require Cwd;return path(Cwd::getcwd(),$_[0]->[PATH])unless defined$base;$base=path($base);return path(($base->is_absolute ? $base : $base->absolute),$_[0]->[PATH])}sub append {my ($self,@data)=@_;my$args=(@data && ref$data[0]eq 'HASH')? shift@data : {};$args=_get_args($args,qw/binmode truncate/);my$binmode=$args->{binmode};$binmode=((caller(0))[10]|| {})->{'open>'}unless defined$binmode;my$mode=$args->{truncate}? ">" : ">>";my$fh=$self->filehandle({locked=>1 },$mode,$binmode);print {$fh}map {ref eq 'ARRAY' ? @$_ : $_}@data;close$fh or $self->_throw('close')}sub append_raw {my ($self,@data)=@_;my$args=(@data && ref$data[0]eq 'HASH')? shift@data : {};$args=_get_args($args,qw/binmode truncate/);$args->{binmode}=':unix';append($self,$args,@data)}sub append_utf8 {my ($self,@data)=@_;my$args=(@data && ref$data[0]eq 'HASH')? shift@data : {};$args=_get_args($args,qw/binmode truncate/);if (defined($HAS_UU)? $HAS_UU : ($HAS_UU=_check_UU())){$args->{binmode}=":unix";append($self,$args,map {Unicode::UTF8::encode_utf8($_)}@data)}elsif (defined($HAS_PU)? $HAS_PU : ($HAS_PU=_check_PU())){$args->{binmode}=":unix:utf8_strict";append($self,$args,@data)}else {$args->{binmode}=":unix:encoding(UTF-8)";append($self,$args,@data)}}sub assert {my ($self,$assertion)=@_;return$self unless$assertion;if (ref$assertion eq 'CODE'){local $_=$self;$assertion->()or Path::Tiny::Error->throw("assert",$self->[PATH],"failed assertion")}else {Carp::croak("argument to assert must be a code reference argument")}return$self}sub basename {my ($self,@suffixes)=@_;$self->_splitpath unless defined$self->[FILE];my$file=$self->[FILE];for my$s (@suffixes){my$re=ref($s)eq 'Regexp' ? qr/$s$/ : qr/\Q$s\E$/;last if$file =~ s/$re//}return$file}sub canonpath {$_[0]->[CANON]}sub cached_temp {my$self=shift;$self->_throw("cached_temp",$self,"has no cached File::Temp object")unless defined$self->[TEMP];return$self->[TEMP]}sub child {my ($self,@parts)=@_;return path($self->[PATH],@parts)}sub children {my ($self,$filter)=@_;my$dh;opendir$dh,$self->[PATH]or $self->_throw('opendir');my@children=readdir$dh;closedir$dh or $self->_throw('closedir');if (not defined$filter){@children=grep {$_ ne '.' && $_ ne '..'}@children}elsif ($filter && ref($filter)eq 'Regexp'){@children=grep {$_ ne '.' && $_ ne '..' && $_ =~ $filter}@children}else {Carp::croak("Invalid argument '$filter' for children()")}return map {path($self->[PATH],$_)}@children}sub chmod {my ($self,$new_mode)=@_;my$mode;if ($new_mode =~ /\d/){$mode=($new_mode =~ /^0/ ? oct($new_mode): $new_mode)}elsif ($new_mode =~ /[=+-]/){$mode=_symbolic_chmod($self->stat->mode & 07777,$new_mode)}else {Carp::croak("Invalid mode argument '$new_mode' for chmod()")}CORE::chmod($mode,$self->[PATH])or $self->_throw("chmod");return 1}sub copy {my ($self,$dest)=@_;require File::Copy;File::Copy::copy($self->[PATH],$dest)or Carp::croak("copy failed for $self to $dest: $!");return -d $dest ? path($dest,$self->basename): path($dest)}sub digest {my ($self,@opts)=@_;my$args=(@opts && ref$opts[0]eq 'HASH')? shift@opts : {};$args=_get_args($args,qw/chunk_size/);unshift@opts,'SHA-256' unless@opts;require Digest;my$digest=Digest->new(@opts);if ($args->{chunk_size}){my$fh=$self->filehandle({locked=>1 },"<",":unix");my$buf;$digest->add($buf)while read$fh,$buf,$args->{chunk_size}}else {$digest->add($self->slurp_raw)}return$digest->hexdigest}sub dirname {my ($self)=@_;$self->_splitpath unless defined$self->[DIR];return length$self->[DIR]? $self->[DIR]: "."}sub edit {my$self=shift;my$cb=shift;my$args=_get_args(shift,qw/binmode/);Carp::croak("Callback for edit() must be a code reference")unless defined($cb)&& ref($cb)eq 'CODE';local $_=$self->slurp(exists($args->{binmode})? {binmode=>$args->{binmode}}: ());$cb->();$self->spew($args,$_);return}sub edit_utf8 {my ($self,$cb)=@_;Carp::croak("Callback for edit_utf8() must be a code reference")unless defined($cb)&& ref($cb)eq 'CODE';local $_=$self->slurp_utf8;$cb->();$self->spew_utf8($_);return}sub edit_raw {$_[2]={binmode=>":unix" };goto&edit}sub edit_lines {my$self=shift;my$cb=shift;my$args=_get_args(shift,qw/binmode/);Carp::croak("Callback for edit_lines() must be a code reference")unless defined($cb)&& ref($cb)eq 'CODE';my$binmode=$args->{binmode};$binmode=((caller(0))[10]|| {})->{'open>'}unless defined$binmode;my$resolved_path=$self->_resolve_symlinks;my$temp=path($resolved_path .$$ .int(rand(2**31)));my$temp_fh=$temp->filehandle({exclusive=>1,locked=>1 },">",$binmode);my$in_fh=$self->filehandle({locked=>1 },'<',$binmode);local $_;while (<$in_fh>){$cb->();$temp_fh->print($_)}close$temp_fh or $self->_throw('close',$temp);close$in_fh or $self->_throw('close');return$temp->move($resolved_path)}sub edit_lines_raw {$_[2]={binmode=>":unix" };goto&edit_lines}sub edit_lines_utf8 {$_[2]={binmode=>":raw:encoding(UTF-8)" };goto&edit_lines}sub exists {-e $_[0]->[PATH]}sub is_file {-e $_[0]->[PATH]&&!-d _}sub is_dir {-d $_[0]->[PATH]}sub filehandle {my ($self,@args)=@_;my$args=(@args && ref$args[0]eq 'HASH')? shift@args : {};$args=_get_args($args,qw/locked exclusive/);$args->{locked}=1 if$args->{exclusive};my ($opentype,$binmode)=@args;$opentype="<" unless defined$opentype;Carp::croak("Invalid file mode '$opentype'")unless grep {$opentype eq $_}qw/< +< > +> >> +>>/;$binmode=((caller(0))[10]|| {})->{'open' .substr($opentype,-1,1)}unless defined$binmode;$binmode="" unless defined$binmode;my ($fh,$lock,$trunc);if ($HAS_FLOCK && $args->{locked}){require Fcntl;if (grep {$opentype eq $_}qw(> +>)){my$flags=$opentype eq ">" ? Fcntl::O_WRONLY(): Fcntl::O_RDWR();$flags |= Fcntl::O_CREAT();$flags |= Fcntl::O_EXCL()if$args->{exclusive};sysopen($fh,$self->[PATH],$flags)or $self->_throw("sysopen");if ($binmode =~ s/^:unix//){binmode($fh,":raw")or $self->_throw("binmode (:raw)");while (1 < (my$layers=()=PerlIO::get_layers($fh,output=>1))){binmode($fh,":pop")or $self->_throw("binmode (:pop)")}}if (length$binmode){binmode($fh,$binmode)or $self->_throw("binmode ($binmode)")}$lock=Fcntl::LOCK_EX();$trunc=1}elsif ($^O eq 'aix' && $opentype eq "<"){if (-w $self->[PATH]){$opentype="+<";$lock=Fcntl::LOCK_EX()}}else {$lock=$opentype eq "<" ? Fcntl::LOCK_SH(): Fcntl::LOCK_EX()}}unless ($fh){my$mode=$opentype .$binmode;open$fh,$mode,$self->[PATH]or $self->_throw("open ($mode)")}do {flock($fh,$lock)or $self->_throw("flock ($lock)")}if$lock;do {truncate($fh,0)or $self->_throw("truncate")}if$trunc;return$fh}sub is_absolute {substr($_[0]->dirname,0,1)eq '/'}sub is_relative {substr($_[0]->dirname,0,1)ne '/'}sub is_rootdir {my ($self)=@_;$self->_splitpath unless defined$self->[DIR];return$self->[DIR]eq '/' && $self->[FILE]eq ''}sub iterator {my$self=shift;my$args=_get_args(shift,qw/recurse follow_symlinks/);my@dirs=$self;my$current;return sub {my$next;while (@dirs){if (ref$dirs[0]eq 'Path::Tiny'){if (!-r $dirs[0]){shift@dirs and next}$current=$dirs[0];my$dh;opendir($dh,$current->[PATH])or $self->_throw('opendir',$current->[PATH]);$dirs[0]=$dh;if (-l $current->[PATH]&&!$args->{follow_symlinks}){shift@dirs and next}}while (defined($next=readdir$dirs[0])){next if$next eq '.' || $next eq '..';my$path=$current->child($next);push@dirs,$path if$args->{recurse}&& -d $path &&!(!$args->{follow_symlinks}&& -l $path);return$path}shift@dirs}return}}sub lines {my$self=shift;my$args=_get_args(shift,qw/binmode chomp count/);my$binmode=$args->{binmode};$binmode=((caller(0))[10]|| {})->{'open<'}unless defined$binmode;my$fh=$self->filehandle({locked=>1 },"<",$binmode);my$chomp=$args->{chomp};if ($args->{count}){my ($counter,$mod,@result)=(0,abs($args->{count}));while (my$line=<$fh>){$line =~ s/(?:\x{0d}?\x{0a}|\x{0d})$// if$chomp;$result[$counter++ ]=$line;last if$counter==$args->{count};$counter %= $mod}splice(@result,0,0,splice(@result,$counter))if@result==$mod && $counter % $mod;return@result}elsif ($chomp){return map {s/(?:\x{0d}?\x{0a}|\x{0d})$//;$_}<$fh>}else {return wantarray ? <$fh> : (my$count=()=<$fh>)}}sub lines_raw {my$self=shift;my$args=_get_args(shift,qw/binmode chomp count/);if ($args->{chomp}&&!$args->{count}){return split /\n/,slurp_raw($self)}else {$args->{binmode}=":raw";return lines($self,$args)}}my$CRLF=qr/(?:\x{0d}?\x{0a}|\x{0d})/;sub lines_utf8 {my$self=shift;my$args=_get_args(shift,qw/binmode chomp count/);if ((defined($HAS_UU)? $HAS_UU : ($HAS_UU=_check_UU()))&& $args->{chomp}&&!$args->{count}){my$slurp=slurp_utf8($self);$slurp =~ s/$CRLF$//;return split$CRLF,$slurp,-1}elsif (defined($HAS_PU)? $HAS_PU : ($HAS_PU=_check_PU())){$args->{binmode}=":unix:utf8_strict";return lines($self,$args)}else {$args->{binmode}=":raw:encoding(UTF-8)";return lines($self,$args)}}sub mkpath {my ($self,$args)=@_;$args={}unless ref$args eq 'HASH';my$err;$args->{error}=\$err unless defined$args->{error};require File::Path;my@dirs=File::Path::make_path($self->[PATH],$args);if ($err && @$err){my ($file,$message)=%{$err->[0]};Carp::croak("mkpath failed for $file: $message")}return@dirs}sub move {my ($self,$dst)=@_;return rename($self->[PATH],$dst)|| $self->_throw('rename',$self->[PATH]."' -> '$dst")}my%opens=(opena=>">>",openr=>"<",openw=>">",openrw=>"+<");while (my ($k,$v)=each%opens){no strict 'refs';*{$k}=sub {my ($self,@args)=@_;my$args=(@args && ref$args[0]eq 'HASH')? shift@args : {};$args=_get_args($args,qw/locked/);my ($binmode)=@args;$binmode=((caller(0))[10]|| {})->{'open' .substr($v,-1,1)}unless defined$binmode;$self->filehandle($args,$v,$binmode)};*{$k ."_raw"}=sub {my ($self,@args)=@_;my$args=(@args && ref$args[0]eq 'HASH')? shift@args : {};$args=_get_args($args,qw/locked/);$self->filehandle($args,$v,":raw")};*{$k ."_utf8"}=sub {my ($self,@args)=@_;my$args=(@args && ref$args[0]eq 'HASH')? shift@args : {};$args=_get_args($args,qw/locked/);$self->filehandle($args,$v,":raw:encoding(UTF-8)")}}sub parent {my ($self,$level)=@_;$level=1 unless defined$level && $level > 0;$self->_splitpath unless defined$self->[FILE];my$parent;if (length$self->[FILE]){if ($self->[FILE]eq '.' || $self->[FILE]eq ".."){$parent=path($self->[PATH]."/..")}else {$parent=path(_non_empty($self->[VOL].$self->[DIR]))}}elsif (length$self->[DIR]){if ($self->[DIR]=~ m{(?:^\.\./|/\.\./|/\.\.$)}){$parent=path($self->[VOL].$self->[DIR]."/..")}else {(my$dir=$self->[DIR])=~ s{/[^\/]+/$}{/};$parent=path($self->[VOL].$dir)}}else {$parent=path(_non_empty($self->[VOL]))}return$level==1 ? $parent : $parent->parent($level - 1)}sub _non_empty {my ($string)=shift;return ((defined($string)&& length($string))? $string : ".")}sub realpath {my$self=shift;$self=$self->_resolve_symlinks;require Cwd;$self->_splitpath if!defined$self->[FILE];my$check_parent=length$self->[FILE]&& $self->[FILE]ne '.' && $self->[FILE]ne '..';my$realpath=eval {local$SIG{__WARN__}=sub {};Cwd::realpath($check_parent ? $self->parent->[PATH]: $self->[PATH])};$self->_throw("resolving realpath")unless defined$realpath && length$realpath && -e $realpath;return ($check_parent ? path($realpath,$self->[FILE]): path($realpath))}sub relative {my ($self,$base)=@_;$base=path(defined$base && length$base ? $base : '.');$self=$self->absolute if$self->is_relative;$base=$base->absolute if$base->is_relative;$self=$self->absolute if!length$self->volume && length$base->volume;$base=$base->absolute if length$self->volume &&!length$base->volume;if (!_same($self->volume,$base->volume)){Carp::croak("relative() can't cross volumes: '$self' vs '$base'")}return path(".")if _same($self->[PATH],$base->[PATH]);if ($base->subsumes($self)){$base="" if$base->is_rootdir;my$relative="$self";$relative =~ s{\A\Q$base/}{};return path($relative)}my (@common,@self_parts,@base_parts);@base_parts=split /\//,$base->_just_filepath;if ($self->is_rootdir){@common=("");shift@base_parts}else {@self_parts=split /\//,$self->_just_filepath;while (@self_parts && @base_parts && _same($self_parts[0],$base_parts[0])){push@common,shift@base_parts;shift@self_parts}}if (my$new_base=$self->_resolve_between(\@common,\@base_parts)){return$self->relative($new_base)}my@new_path=(("..")x (0+ @base_parts),@self_parts);return path(@new_path)}sub _just_filepath {my$self=shift;my$self_vol=$self->volume;return "$self" if!length$self_vol;(my$self_path="$self")=~ s{\A\Q$self_vol}{};return$self_path}sub _resolve_between {my ($self,$common,$base)=@_;my$path=$self->volume .join("/",@$common);my$changed=0;for my$p (@$base){$path .= "/$p";if ($p eq '..'){$changed=1;if (-e $path){$path=path($path)->realpath->[PATH]}else {$path =~ s{/[^/]+/..$}{/}}}if (-l $path){$changed=1;$path=path($path)->realpath->[PATH]}}return$changed ? path($path): undef}sub remove {my$self=shift;return 0 if!-e $self->[PATH]&&!-l $self->[PATH];return unlink($self->[PATH])|| $self->_throw('unlink')}sub remove_tree {my ($self,$args)=@_;return 0 if!-e $self->[PATH]&&!-l $self->[PATH];$args={}unless ref$args eq 'HASH';my$err;$args->{error}=\$err unless defined$args->{error};$args->{safe}=1 unless defined$args->{safe};require File::Path;my$count=File::Path::remove_tree($self->[PATH],$args);if ($err && @$err){my ($file,$message)=%{$err->[0]};Carp::croak("remove_tree failed for $file: $message")}return$count}sub sibling {my$self=shift;return path($self->parent->[PATH],@_)}sub slurp {my$self=shift;my$args=_get_args(shift,qw/binmode/);my$binmode=$args->{binmode};$binmode=((caller(0))[10]|| {})->{'open<'}unless defined$binmode;my$fh=$self->filehandle({locked=>1 },"<",$binmode);if ((defined($binmode)? $binmode : "")eq ":unix" and my$size=-s $fh){my$buf;read$fh,$buf,$size;return$buf}else {local $/;return scalar <$fh>}}sub slurp_raw {$_[1]={binmode=>":unix" };goto&slurp}sub slurp_utf8 {if (defined($HAS_UU)? $HAS_UU : ($HAS_UU=_check_UU())){return Unicode::UTF8::decode_utf8(slurp($_[0],{binmode=>":unix" }))}elsif (defined($HAS_PU)? $HAS_PU : ($HAS_PU=_check_PU())){$_[1]={binmode=>":unix:utf8_strict" };goto&slurp}else {$_[1]={binmode=>":raw:encoding(UTF-8)" };goto&slurp}}sub spew {my ($self,@data)=@_;my$args=(@data && ref$data[0]eq 'HASH')? shift@data : {};$args=_get_args($args,qw/binmode/);my$binmode=$args->{binmode};$binmode=((caller(0))[10]|| {})->{'open>'}unless defined$binmode;my$resolved_path=$self->_resolve_symlinks;my$temp=path($resolved_path .$$ .int(rand(2**31)));my$fh=$temp->filehandle({exclusive=>1,locked=>1 },">",$binmode);print {$fh}map {ref eq 'ARRAY' ? @$_ : $_}@data;close$fh or $self->_throw('close',$temp->[PATH]);return$temp->move($resolved_path)}sub spew_raw {splice @_,1,0,{binmode=>":unix" };goto&spew}sub spew_utf8 {if (defined($HAS_UU)? $HAS_UU : ($HAS_UU=_check_UU())){my$self=shift;spew($self,{binmode=>":unix" },map {Unicode::UTF8::encode_utf8($_)}map {ref eq 'ARRAY' ? @$_ : $_}@_)}elsif (defined($HAS_PU)? $HAS_PU : ($HAS_PU=_check_PU())){splice @_,1,0,{binmode=>":unix:utf8_strict" };goto&spew}else {splice @_,1,0,{binmode=>":unix:encoding(UTF-8)" };goto&spew}}sub stat {my$self=shift;require File::stat;return File::stat::stat($self->[PATH])|| $self->_throw('stat')}sub lstat {my$self=shift;require File::stat;return File::stat::lstat($self->[PATH])|| $self->_throw('lstat')}sub stringify {$_[0]->[PATH]}sub subsumes {my$self=shift;Carp::croak("subsumes() requires a defined, positive-length argument")unless defined $_[0];my$other=path(shift);if ($self->is_absolute &&!$other->is_absolute){$other=$other->absolute}elsif ($other->is_absolute &&!$self->is_absolute){$self=$self->absolute}if (length$self->volume &&!length$other->volume){$other=$other->absolute}elsif (length$other->volume &&!length$self->volume){$self=$self->absolute}if ($self->[PATH]eq '.'){return!!1}elsif ($self->is_rootdir){return$other->[PATH]=~ m{^\Q$self->[PATH]\E}}else {return$other->[PATH]=~ m{^\Q$self->[PATH]\E(?:/|$)}}}sub touch {my ($self,$epoch)=@_;if (!-e $self->[PATH]){my$fh=$self->openw;close$fh or $self->_throw('close')}if (defined$epoch){utime$epoch,$epoch,$self->[PATH]or $self->_throw("utime ($epoch)")}else {utime undef,undef,$self->[PATH]or $self->_throw("utime ()")}return$self}sub touchpath {my ($self)=@_;my$parent=$self->parent;$parent->mkpath unless$parent->exists;$self->touch}sub visit {my$self=shift;my$cb=shift;my$args=_get_args(shift,qw/recurse follow_symlinks/);Carp::croak("Callback for visit() must be a code reference")unless defined($cb)&& ref($cb)eq 'CODE';my$next=$self->iterator($args);my$state={};while (my$file=$next->()){local $_=$file;my$r=$cb->($file,$state);last if ref($r)eq 'SCALAR' &&!$$r}return$state}sub volume {my ($self)=@_;$self->_splitpath unless defined$self->[VOL];return$self->[VOL]}package Path::Tiny::Error;our@CARP_NOT=qw/Path::Tiny/;use overload (q{""}=>sub {(shift)->{msg}},fallback=>1);sub throw {my ($class,$op,$file,$err)=@_;chomp(my$trace=Carp::shortmess);my$msg="Error $op on '$file': $err$trace\n";die bless {op=>$op,file=>$file,err=>$err,msg=>$msg },$class}1;
623 PATH_TINY
624
625 $fatpacked{"Smart/Options.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'SMART_OPTIONS';
626 package Smart::Options;use strict;use warnings;use 5.010001;our$VERSION='0.061';require Exporter;our@ISA=qw(Exporter);our@EXPORT=qw(argv);use List::MoreUtils qw(uniq);use Text::Table;use File::Slurp;sub new {my$pkg=shift;my%opt=@_;my$self=bless {alias=>{},default=>{},boolean=>{},demand=>{},usage=>"Usage: $0",describe=>{},type=>{},subcmd=>{},coerce=>{},env=>{},env_prefix=>'',},$pkg;if ($opt{add_help}// 1){$self->options(h=>{alias=>'help',describe=>'show help',});$self->{add_help}=1}$self}sub argv {Smart::Options->new->parse(@_)}sub _set {my$self=shift;my$param=shift;my%args=@_;for my$option (keys%args){$self->{$param}->{$option}=$args{$option}}$self}sub alias {shift->_set('alias',@_)}sub default {shift->_set('default',@_)}sub describe {shift->_set('describe',@_)}sub type {shift->_set('type',@_)}sub subcmd {shift->_set('subcmd',@_)}sub _set_flag {my$self=shift;my$param=shift;for my$option (@_){$self->{$param}->{$option}=1}$self}sub boolean {shift->_set_flag('boolean',@_)}sub demand {shift->_set_flag('demand',@_)}sub env {shift->_set_flag('env',@_)}sub options {my$self=shift;my%args=@_;while (my($opt,$setting)=each%args){for my$key (keys %$setting){$self->$key($opt,$setting->{$key})}}$self}sub coerce {my ($self,$isa,$type,$generater)=@_;$self->{coerce}->{$isa}={type=>$type,generater=>$generater,};$self}sub usage {$_[0]->{usage}=$_[1];$_[0]}sub env_prefix {$_[0]->{env_prefix}=$_[1];$_[0]}sub _get_opt_desc {my ($self,$option)=@_;my@opts=($option);while (my($opt,$val)=each %{$self->{alias}}){push@opts,$opt if$val eq $option}return join(', ',map {(length($_)==1 ? '-' : '--').$_}sort@opts)}sub _get_describe {my ($self,$option)=@_;my$desc=$self->{describe}->{$option};while (my($opt,$val)=each %{$self->{alias}}){$desc ||= $self->{describe}->{$opt}if$val eq $option}return$desc ? ucfirst($desc): ''}sub _get_default {my ($self,$option)=@_;my$value=$self->{default}->{$option};while (my($opt,$val)=each %{$self->{alias}}){$value ||= $self->{default}->{$opt}if$val eq $option}$value}sub help {my$self=shift;my$alias=$self->{alias};my$demand=$self->{demand};my$describe=$self->{describe};my$default=$self->{default};my$boolean=$self->{boolean};my$help=$self->{usage}."\n";if (scalar(keys %$demand)or scalar(keys %$describe)){my@opts;for my$opt (uniq sort keys %$demand,keys %$describe,keys %$default,keys %$boolean,values %$alias){next if$alias->{$opt};push@opts,[$self->_get_opt_desc($opt),$self->_get_describe($opt),$boolean->{$opt}? '[boolean]' : '',$demand->{$opt}? '[required]' : '',$self->_get_default($opt)? "[default: @{[$self->_get_default($opt)]}]" : '',]}my$sep=\' ';$help .= "\nOptions:\n";$help .= Text::Table->new($sep,'',$sep,'',$sep,'',$sep,'',$sep,'')->load(@opts)->stringify ."\n";if (keys %{$self->{subcmd}}){$help .= "Implemented commands are:\n";$help .= " " .join(', ',sort keys %{$self->{subcmd}})."\n\n"}}$help}sub showHelp {my ($self,$fh)=@_;$fh //= *STDERR;print$fh $self->help}sub _set_v2a {my ($argv,$key,$value,$k)=@_;if ($k){$argv->{$key}//= {};_set_v2a($argv->{$key},$k,$value)}elsif (exists$argv->{$key}){if (ref($argv->{$key})){push @{$argv->{$key}},$value}else {$argv->{$key}=[$argv->{$key},$value ]}}else {$argv->{$key}=$value}}sub _get_real_name {my ($self,$opt)=@_;while (my$name=$self->{alias}->{$opt}){$opt=$name}return$opt}sub _load_config {my ($self,$argv,$file)=@_;for my$line (read_file($file)){next if$line =~ /^\[/;next if$line =~ /^;/;next if$line !~ /=/;chomp($line);if ($line =~ /^(.+?[^\\])=(.*)$/){$argv->{$1}=$2}}}sub parse {my$self=shift;push @_,@ARGV unless @_;my$argv={};my@args;my$boolean=$self->{boolean};my$key;my$nest_key;my$stop=0;for my$arg (@_){if ($stop){push@args,$arg;next}if ($arg =~ /^--((?:\w|-|\.)+)=(.+)$/){my ($opt,$k)=split(/\./,$1);my$option=$self->_get_real_name($opt);if ($k){_set_v2a($argv,$option,$2,$k)}else {_set_v2a($argv,$option,$2)}}elsif ($arg =~ /^(-(\w)|--((?:\w|-|\.)+))$/){if ($key){$argv->{$key}=1}my$opt=$2 // $3;if ($opt =~ /^no\-(.+)$/){my$option=$self->_get_real_name($1);$argv->{$option}=0;next}($opt,my$k)=split(/\./,$opt);my$option=$self->_get_real_name($opt);if ($boolean->{$option}){if ($k){$argv->{$option}//= {};$argv->{$option}->{$k}=1}else {$argv->{$option}=1}}else {$key=$option;$nest_key=$k}}elsif ($arg =~ /^-(\w(?:\w|-|\.)+)$/){if ($key){$argv->{$key}=1}my$opt_str=$1;if ($opt_str =~ /^(.)([0-9])+$/){my$option=$self->_get_real_name($1);$argv->{$option}=$2}else {for (split //,$opt_str){my$option=$self->_get_real_name($_);$argv->{$option}=1}}}elsif ($arg =~ /^--$/){$stop=1;next}else {if ($key){if ($nest_key){_set_v2a($argv,$key,$arg,$nest_key)}else {_set_v2a($argv,$key,$arg)}$key=$nest_key=undef}else {if (!scalar(@args)&& keys %{$self->{subcmd}}){if ($self->{subcmd}->{$arg}){$argv->{command}=$arg;$stop=1;next}else {die "sub command '$arg' not defined."}}push@args,$arg}}}if ($key){if ($nest_key){$argv->{$key}//= {};$argv->{$key}->{$nest_key}=1}else {$argv->{$key}=1}}if (my$parser=$self->{subcmd}->{$argv->{command}||''}){$argv->{cmd_option}=$parser->parse(@args)}else {$argv->{_}=\@args}for my$env (keys %{$self->{env}}){if (defined($ENV{uc($self->{env_prefix}."_$env")})){my$option=$self->_get_real_name($env);$argv->{$option}//= $ENV{uc($self->{env_prefix}."_$env")}}}while (my ($key,$val)=each %{$self->{default}}){my$opt=$self->_get_real_name($key);if (ref($val)&& ref($val)eq 'CODE'){$argv->{$opt}//= $val->()}else {$argv->{$opt}//= $val}}while (my ($key,$val)=each %{$self->{type}}){next if$val ne 'Config';next if!($argv->{$key})||!(-f $argv->{$key});$self->_load_config($argv,delete$argv->{$key})}for my$key (keys %{$self->{demand}}){my$opt=$self->_get_real_name($key);if (!$argv->{$opt}){$self->showHelp;print STDERR "\nMissing required arguments: $opt\n";die}}for my$key (keys %{$self->{type}}){my$opt=$self->_get_real_name($key);my$type=$self->{type}->{$key};if (my$c=$self->{coerce}->{$type}){$type=$c->{type};$argv->{$opt}=$c->{generater}->($argv->{$opt})}my$check=0;if ($type eq 'Bool'){$argv->{$opt}//= 0;$check=($argv->{$opt}=~ /^(0|1)$/)? 1 : 0}elsif ($type eq 'Str'){$check=1}elsif ($type eq 'Int'){if ($argv->{$opt}){$check=($argv->{$opt}=~ /^\-?\d+$/)? 1 : 0}else {$check=1}}elsif ($type eq 'Num'){if ($argv->{$opt}){$check=($argv->{$opt}=~ /^\-?\d+(\.\d+)$/)? 1 : 0}else {$check=1}}elsif ($type eq 'ArrayRef'){$argv->{$opt}//= [];unless (ref($argv->{$opt})){$argv->{$opt}=[$argv->{$opt}]}$check=(ref($argv->{$opt})eq 'ARRAY')? 1 : 0}elsif ($type eq 'HashRef'){$argv->{$opt}//= {};$check=(ref($argv->{$opt})eq 'HASH')? 1 : 0}elsif ('Config'){if ($argv->{$opt}&&!(-f $argv->{$opt})){die "cannot load config file '@{[$argv->{$opt}]}\n"}$check=1}else {die "cannot find type constraint '$type'\n"}unless ($check){die "Value '@{[$argv->{$opt}]}' invalid for option $opt($type)\n"}}if ($argv->{help}&& $self->{add_help}){$self->showHelp;die}$argv}1;
627 SMART_OPTIONS
628
629 $fatpacked{"Smart/Options/Declare.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'SMART_OPTIONS_DECLARE';
630 package Smart::Options::Declare;use strict;use warnings;use Exporter 'import';use Smart::Options;use PadWalker qw/var_name/;our@EXPORT=qw(opts opts_coerce);our$COERCE={Multiple=>{type=>'ArrayRef',generater=>sub {if (defined $_[0]){return [split(qr{,},ref($_[0])eq 'ARRAY' ? join(q{,},@{$_[0]}): $_[0])]}else {return $_[0]}}}};my%is_invocant=map{$_=>undef}qw($self $class);sub opts {{package DB;()=caller(1)}if (exists$is_invocant{var_name(1,\$_[0])|| '' }){$_[0]=shift@DB::args;shift}my$opt=Smart::Options->new();$opt->type(config=>'Config');for (my$i=0 ;$i < @_ ;$i++ ){(my$name=var_name(1,\$_[$i]))or Carp::croak('usage: opts my $var => TYPE, ...');$name =~ s/^\$//;if ($name =~ /_/){(my$newname=$name)=~ s/_/-/g;$opt->alias($newname=>$name);$name=$newname}my$rule=$_[$i+1];if ($rule){if (ref($rule)&& ref($rule)eq 'HASH'){if ($rule->{default}){$opt->default($name=>$rule->{default})}if ($rule->{required}){$opt->demand($name)}if ($rule->{alias}){$opt->alias($rule->{alias}=>$name)}if ($rule->{comment}){$opt->describe($name=>$rule->{comment})}if (my$isa=$rule->{isa}){if ($isa eq 'Bool'){$opt->boolean($name)}$opt->type($name=>$isa)}}else {if ($rule eq 'Bool'){$opt->boolean($name)}$opt->type($name=>$rule)}}if (length($name)> 1){$opt->alias(substr($name,0,1)=>$name)}$i++ if defined $_[$i+1]}while (my ($isa,$c)=each(%$COERCE)){$opt->coerce($isa=>$c->{type},$c->{generater})}my$argv=$opt->parse;for (my$i=0 ;$i < @_ ;$i++ ){(my$name=var_name(1,\$_[$i]))or Carp::croak('usage: opts my $var => TYPE, ...');$name =~ s/^\$//;$_[$i]=$argv->{$name};$i++ if defined $_[$i+1]}}sub opts_coerce {my ($isa,$type,$generater)=@_;$COERCE->{$isa}={type=>$type,generater=>$generater }}1;
631 SMART_OPTIONS_DECLARE
632
633 $fatpacked{"Text/Aligner.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TEXT_ALIGNER';
634 package Text::Aligner;use strict;use warnings;use 5.008;BEGIN {use Exporter ();use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);$VERSION='0.13';@ISA=qw (Exporter);@EXPORT=qw ();@EXPORT_OK=qw ( align);%EXPORT_TAGS=()}sub align ($@) {my$ali=Text::Aligner->new(shift);$ali->_alloc(map ref eq 'SCALAR' ? $$_ : $_,@_);if (defined wantarray){my@just=map$ali->_justify(ref eq 'SCALAR' ? $$_ : $_),@_;return@just if wantarray;return join "\n",@just,''}else {for (@_){$_=$ali->_justify($_)for ref eq 'SCALAR' ? $$_ : $_}}}sub _new {my$class=shift;my ($width,$pos)=@_;bless {width=>$width,pos=>$pos,left=>Text::Aligner::MaxKeeper->new,right=>Text::Aligner::MaxKeeper->new,},$class}sub new {my ($class,$spec)=@_;$spec ||= 0;my$al;if (!ref($spec)and $spec =~ s/^auto/num/){$al=Text::Aligner::Auto->_new($spec)}else {$al=$class->_new(_compile_alispec($spec))}$al}sub _measure0 {my$al=shift;my$obj=shift;$obj='' unless defined$obj;my ($w,$p);if (ref$obj){($w,$p)=($obj->$al->{width}->(),$obj->$al->{pos}->())}else {($w,$p)=($al->{width}->($obj),$al->{pos}->($obj))}$_ ||= 0 for$w,$p;($p,$w - $p)}use Term::ANSIColor 2.02;sub _measure {my$al=shift;my$obj=shift;$obj='' unless defined$obj;my ($wmeth,$pmeth)=@{$al}{qw(width pos)};$obj=Term::ANSIColor::colorstrip($obj)unless ref$obj;my$w=ref$wmeth ? $wmeth->($obj): $obj->$wmeth;my$p=ref$pmeth ? $pmeth->($obj): $obj->$pmeth;$_ ||= 0 for$w,$p;($p,$w - $p)}sub _status {my@lr=($_[0]->{left}->max,$_[0]->{right}->max);return unless defined($lr[0])and defined($lr[1]);@lr}sub _alloc {my$al=shift;for (@_){my ($l,$r)=$al->_measure($_);$al->{left}->remember($l);$al->{right}->remember($r)}$al}sub _forget {my$al=shift;for (map defined()? $_ : '',@_){my ($l,$r)=$al->_measure($_);$al->{left}->forget($l);$al->{right}->forget($r)}$al}sub _spaces {my ($repeat_count)=@_;return (($repeat_count > 0)? (' ' x $repeat_count): '')}sub _justify {my$al=shift;my$str=shift;$str .= '';my ($l_pad,$r_pad)=$al->_padding($str);substr($str,0,-$l_pad)='' if$l_pad < 0;substr($str,$r_pad)='' if$r_pad < 0;return _spaces($l_pad).$str ._spaces($r_pad)}sub _padding {my$al=shift;my$str=shift;my ($this_l,$this_r)=$al->_measure($str);my ($l_pad,$r_pad)=(0,0);if ($al->_status){($l_pad,$r_pad)=$al->_status;$l_pad -= $this_l;$r_pad -= $this_r}($l_pad,$r_pad)}sub _compile_alispec {my$width=sub {length shift};my$pos;local $_=shift || '';if (ref()eq 'Regexp'){my$regex=$_;$pos=sub {local $_=shift;return m/$regex/ ? $-[0]: length}}else {s/^left/0/;s/^center/0.5/;s/^right/1/;if (_is_number($_)){my$proportion=$_;$pos=sub {int($proportion*length shift)}}elsif ($_ =~ /^(?:num|point)(?:\((.*))?/){my$point=defined $1 ? $1 : '';$point =~ s/\)$//;length$point or $point='.';$pos=sub {index(shift().$point,$point)}}else {$pos=sub {0}}}($width,$pos)}sub _is_number {my ($x)=@_;return 0 unless defined$x;return 0 if$x !~ /\d/;return 1 if$x =~ /^-?\d+\.?\d*$/;$x=Term::ANSIColor::colorstrip($x);$x =~ /^-?\d+\.?\d*$/}package Text::Aligner::Auto;sub _new {my$class=shift;my$numspec=shift;bless {num=>Text::Aligner->new('num'),other=>Text::Aligner->new,},$class}sub _alloc {my$aa=shift;my@num=grep _is_number($_),@_;my@other=grep!_is_number($_),@_;$aa->{num}->_alloc(@num);$aa->{other}->_alloc(@other);$aa}sub _forget {my$aa=shift;$aa->{num}->_forget(grep _is_number($_),@_);$aa->{other}->_forget(grep!_is_number($_),@_);$aa}sub _justify {my ($aa,$str)=@_;$str=$aa->{_is_number($str)? 'num' : 'other'}->_justify($str);my$combi=Text::Aligner->new;$combi->_alloc($aa->{num}->_justify(''))if$aa->{num}->_status;$combi->_alloc($aa->{other}->_justify(''))if$aa->{other}->_status;$combi->_justify($str)}BEGIN {*_is_number=\ &Text::Aligner::_is_number}package Text::Aligner::MaxKeeper;sub new {bless {max=>undef,seen=>{},},shift}sub max {$_[0]->{max}}sub remember {my ($mk,$val)=@_;_to_max($mk->{max},$val);$mk->{seen}->{$val}++;$mk}sub forget {my ($mk,$val)=@_;if (exists$mk->{seen}->{$val}){my$seen=$mk->{seen};unless (--$seen->{$val}){delete$seen->{$val};if ($mk->{max}==$val){undef$mk->{max};_to_max($mk->{max},keys %$seen)}}}$mk}sub _to_max {my$var=\ shift;defined $_ and (not defined $$var or $$var < $_)and $$var=$_ for @_;$$var}1;
635 TEXT_ALIGNER
636
637 $fatpacked{"Text/Table.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TEXT_TABLE';
638 package Text::Table;use strict;use warnings;use 5.008;use List::Util qw(sum max);use Text::Aligner qw(align);our$VERSION='1.133';use overload (bool=>sub {return 1},'""'=>'stringify',);sub _is_sep {my$datum=shift;return (defined($datum)and ((ref($datum)eq 'SCALAR')or (ref($datum)eq 'HASH' and $datum->{is_sep})))}sub _get_sep_title_body {my$sep=shift;return +(ref($sep)eq 'HASH')? @{$sep}{qw(title body)}: split(/\n/,${$sep},-1)}sub _parse_sep {my$sep=shift;if (!defined($sep)){$sep=''}my ($title,$body)=_get_sep_title_body($sep);if (!defined($body)){$body=$title}($title,$body)=align('left',$title,$body);return {is_sep=>1,title=>$title,body=>$body,}}sub _default_if_empty {my ($ref,$default)=@_;if (!(defined($$ref)&& length($$ref))){$$ref=$default}return}sub _is_align {my$align=shift;return$align =~ /\A(?:left|center|right)/}sub _parse_spec {my$spec=shift;if (!defined($spec)){$spec=''}my$alispec=qr/^ *(?:left|center|right|num|point|auto)/;my ($title,$align,$align_title,$align_title_lines,$sample);if (ref ($spec)eq 'HASH'){($title,$align,$align_title,$align_title_lines,$sample)=@{$spec}{qw(title align align_title align_title_lines sample)}}else {my$alispec=qr/&(.*)/;if ($spec =~ $alispec){($title,$align,$sample)=($spec =~ /(.*)^$alispec\n?(.*)/sm)}else {$title=$spec}for my$s ($title,$sample){if (defined($s)){chomp($s)}}}for my$x ($title,$sample){if (!defined($x)){$x=[]}elsif (ref($x)ne 'ARRAY'){$x=[split /\n/,$x,-1]}}_default_if_empty(\$align,'auto');unless (ref$align eq 'Regexp' or $align =~ /^(?:left|center|right|num\(?|point\(?|auto)/){_warn("Invalid align specification: '$align', using 'auto'");$align='auto'}_default_if_empty(\$align_title,'left');if (!_is_align($align_title)){_warn("Invalid align_title specification: " ."'$align_title', using 'left'",);$align_title='left'}_default_if_empty(\$align_title_lines,$align_title);if (!_is_align($align_title_lines)){_warn("Invalid align_title_lines specification: " ."'$align_title_lines', using 'left'",);$align_title_lines='left'}return {title=>$title,align=>$align,align_title=>$align_title,align_title_lines=>$align_title_lines,sample=>$sample,}}sub new {my$tb=bless {},shift;return$tb->_entitle([@_ ])}sub _blank {my$self=shift;if (@_){$self->{blank}=shift}return$self->{blank}}sub _cols {my$self=shift;if (@_){$self->{cols}=shift}return$self->{cols}}sub _forms {my$self=shift;if (@_){$self->{forms}=shift}return$self->{forms}}sub _lines {my$self=shift;if (@_){$self->{lines}=shift}return$self->{lines}}sub _spec {my$self=shift;if (@_){$self->{spec}=shift}return$self->{spec}}sub _titles {my$self=shift;if (@_){$self->{titles}=shift}return$self->{titles}}sub _entitle {my ($tb,$sep_list)=@_;my (@seps,@spec);my$sep;for my$sep_item (@{$sep_list}){if (_is_sep ($sep_item)){$sep=_parse_sep($sep_item)}else {push@seps,$sep;push@spec,_parse_spec($sep_item);undef$sep}}push@seps,$sep;my$title_form=_compile_field_format('title',\@seps);my$body_form=_compile_field_format('body',\@seps);my@titles=map {[@{$_->{title}}]}@spec;my$title_height=max(0,map {scalar(@$_)}@titles);for my$title (@titles){push @{$title},('')x ($title_height - @{$title})}for my$t_idx (0 .. $#titles){align($spec[$t_idx]->{align_title_lines},@{$titles[$t_idx]})}$tb->_spec(\@spec);$tb->_cols([map [],1 .. @spec]);$tb->_forms([$title_form,$body_form]);$tb->_titles(\@titles);$tb->_clear_cache;return$tb}sub _compile_format {my$seps=shift;for my$idx (0 .. $#$seps){if (!defined($seps->[$idx])){$seps->[$idx]=($idx==0 or $idx==$#$seps)? '' : q{ }}else {$seps->[$idx]=~ s/%/%%/g}}return join '%s',@$seps}sub _compile_field_format {my ($field,$seps)=@_;return _compile_format([map {defined($_)? $_->{$field}: undef}@$seps])}sub _recover_separators {my$format=shift;my@seps=split /(?<!%)%s/,$format,-1;for my$s (@seps){$s =~ s/%%/%/g}return \@seps}sub select {my$tb=shift;my@args=map$tb->_select_group($_),@_;my@sel=map$tb->_check_index($_),grep!_is_sep($_),@args;for my$arg (@args){if (!_is_sep($arg)){$arg=$tb->_spec->[$arg]}}my$sub=ref($tb)->new(@args);@{$sub->{cols}}=map {[@$_ ]}@{$tb->_cols}[@sel];$sub}sub _select_group {my ($tb,$group)=@_;return$group unless ref$group eq 'ARRAY';GROUP_LOOP: for my$g (@$group){if (_is_sep($g)){next GROUP_LOOP}$tb->_check_index($g);if (grep {$_}@{$tb->_cols->[$g]}){return @$group}return}return}sub _check_index {my$tb=shift;my ($i)=@_;my$n=$tb->n_cols;my$ok=eval {use warnings FATAL=>'numeric';-$n <= $i and $i < $n};_warn("Invalid column index '$_'")if $@ or not $ok;shift}sub _clear_cache {my ($tb)=@_;$tb->_blank(undef());$tb->_lines(undef());return}sub add {my$tb=shift;if (!$tb->n_cols){$tb->_entitle([('')x @_])}for my$row (_transpose([map {[defined()? split(/\n/): '' ]}@_ ])){$tb->_add(@$row)}$tb->_clear_cache;return$tb}sub _add {my$tb=shift;for my$col (@{$tb->_cols}){push @{$col},shift(@_)}$tb->_clear_cache;return$tb}sub load {my$tb=shift;for my$row (@_){if (!defined($row)){$row=''}$tb->add((ref($row)eq 'ARRAY')? (@$row): (split ' ',$row))}$tb}sub clear {my$tb=shift;for my$col (@{$tb->_cols}){$col=[]}$tb->_clear_cache;return$tb}sub n_cols {scalar @{$_[0]->{spec}}}sub title_height {$_[0]->n_cols and scalar @{$_[0]->_titles->[0]}}sub body_height {my ($tb)=@_;return ($tb->n_cols && scalar @{$tb->_cols->[0]})}sub table_height {my$tb=shift;return$tb->title_height + $tb->body_height}BEGIN {*height=\&table_height}sub width {my ($tb)=@_;return$tb->height && (length(($tb->table(0))[0])- 1)}sub _normalize_col_index {my ($tb,$col_index)=@_;$col_index ||= 0;if ($col_index < 0){$col_index += $tb->n_cols}if ($col_index < 0){$col_index=0}elsif ($col_index > $tb->n_cols){$col_index=$tb->n_cols}return$col_index}sub colrange {my ($tb,$proto_col_index)=@_;my$col_index=$tb->_normalize_col_index($proto_col_index);return (0,0)unless$tb->width;my@widths=map {length}@{$tb->_blank},'';@widths=@widths[0 .. $col_index];my$width=pop@widths;my$pos=sum(@widths)|| 0;my$seps_aref=_recover_separators($tb->_forms->[0]);my$sep_sum=0;for my$sep (@$seps_aref[0 .. $col_index]){$sep_sum += length($sep)}return ($pos+$sep_sum,$width)}sub table {my$tb=shift;return$tb->_table_portion($tb->height,0,@_)}sub title {my$tb=shift;return$tb->_table_portion($tb->title_height,0,@_)}sub body {my$tb=shift;return$tb->_table_portion($tb->body_height,$tb->title_height,@_)}sub stringify {my ($tb)=@_;return (scalar ($tb->table()))}sub _table_portion_as_aref {my$tb=shift;my$total=shift;my$offset=shift;my ($from,$n)=(0,$total);if (@_){$from=shift;$n=@_ ? shift : 1}($from,$n)=_limit_range($total,$from,$n);my$limit=$tb->title_height;$from += $offset;return [map$tb->_assemble_line($_ >= $limit,$tb->_table_line($_),0),$from .. $from + $n - 1 ]}sub _table_portion {my$tb=shift;my$lines_aref=$tb->_table_portion_as_aref(@_);return (wantarray ? @$lines_aref : join('',@$lines_aref))}sub _limit_range {my ($total,$from,$n)=@_;$from ||= 0;$from += $total if$from < 0;$n=$total unless defined$n;return (0,0)if$from + $n < 0 or $from >= $total;$from=0 if$from < 0;$n=$total - $from if$n > $total - $from;return($from,$n)}sub _table_line {my ($tb,$idx)=@_;if (!$tb->_lines){$tb->_lines([$tb->_build_table_lines ])}return$tb->_lines->[$idx]}sub _build_table_lines {my$tb=shift;my@cols=map {[map {defined($_)? $_ : ''}@$_ ]}@{$tb->_cols()};for my$col (@cols){push @$col,''}for my$col_idx (0 .. $#cols){push @{$cols[$col_idx]},@{$tb->_spec->[$col_idx]->{sample}}}for my$col_idx (0 .. $#cols){align($tb->_spec->[$col_idx]->{align},@{$cols[$col_idx]})}for my$col (@cols){splice(@{$col},1 + $tb->body_height)}for my$col_idx (0 .. $#cols){unshift @{$cols[$col_idx]},@{$tb->_titles->[$col_idx]}}for my$col_idx (0 .. $#cols){align($tb->_spec->[$col_idx]->{align_title},@{$cols[$col_idx]})}my@blank;for my$col (@cols){push@blank,pop(@$col)}$tb->_blank(\@blank);return _transpose_n($tb->height,\@cols)}sub _transpose_n {my ($n,$cols)=@_;return map {[map {shift @$_}@$cols]}1 .. $n}sub _transpose {my ($cols)=@_;my$m=max (map {scalar(@$_)}@$cols,[]);return _transpose_n($m,$cols)}sub _assemble_line {my ($tb,$in_body,$line_aref,$replace_spaces)=@_;my$format=$tb->_forms->[!!$in_body];if ($replace_spaces){$format =~ s/\s/=/g}return sprintf($format,@$line_aref)."\n"}sub _text_rule {my ($tb,$rule,$char,$alt)=@_;if (defined$alt){$rule =~ s/(.)/$1 eq ' ' ? $char : $alt/ge}else {$rule =~ s/ /$char/g if$char ne ' '}return$rule}sub _rule {my$tb=shift;return + (!$tb->width)? '' : $tb->_positive_width_rule(@_)}sub _positive_width_rule {my ($tb,$in_body,$char,$alt)=@_;my$rule=$tb->_assemble_line($in_body,$tb->_blank,((ref($char)eq "CODE")? 1 : 0),);return$tb->_render_rule($rule,$char,$alt)}sub _render_rule {my ($tb,$rule,$char,$alt)=@_;if (ref($char)eq "CODE"){return$tb->_render_rule_with_callbacks($rule,$char,$alt)}else {_default_if_empty(\$char,' ');return$tb->_text_rule($rule,$char,$alt)}}sub _get_fixed_len_string {my ($s,$len)=@_;$s=substr($s,0,$len);$s .= ' ' x ($len - length($s));return$s}sub _render_rule_with_callbacks {my ($tb,$rule,$char,$alt)=@_;my%callbacks=('char'=>{cb=>$char,idx=>0,},'alt'=>{cb=>$alt,idx=>0,},);my$calc_substitution=sub {my$s=shift;my$len=length($s);my$which=(($s =~ /\A /)? 'char' : 'alt');my$rec=$callbacks{$which};return _get_fixed_len_string(scalar ($rec->{cb}->($rec->{idx}++,$len)),$len,)};$rule =~ s/((.)\2*)/$calc_substitution->($1)/ge;return$rule}sub rule {my$tb=shift;return$tb->_rule(0,@_)}sub body_rule {my$tb=shift;return$tb->_rule(1,@_)}use Carp;{my ($warn,$fatal)=(0,0);sub warnings {my (undef,$toggle)=@_;$toggle ||= 'on';if ($toggle eq 'off'){($warn,$fatal)=(0,0)}elsif ($toggle eq 'fatal'){($warn,$fatal)=(1,1)}else {($warn,$fatal)=(1,0)}return$fatal ? 'fatal' : $warn ? 'on' : 'off'}sub _warn {my$msg=shift;return unless$warn;if ($fatal){croak($msg)}carp($msg);return}}
639 TEXT_TABLE
640
641 s/^ //mg for values %fatpacked;
642
643 my $class = 'FatPacked::'.(0+\%fatpacked);
644 no strict 'refs';
645 *{"${class}::files"} = sub { keys %{$_[0]} };
646
647 if ($] < 5.008) {
648 *{"${class}::INC"} = sub {
649 if (my $fat = $_[0]{$_[1]}) {
650 my $pos = 0;
651 my $last = length $fat;
652 return (sub {
653 return 0 if $pos == $last;
654 my $next = (1 + index $fat, "\n", $pos) || $last;
655 $_ .= substr $fat, $pos, $next - $pos;
656 $pos = $next;
657 return 1;
658 });
659 }
660 };
661 }
662
663 else {
664 *{"${class}::INC"} = sub {
665 if (my $fat = $_[0]{$_[1]}) {
666 open my $fh, '<', \$fat
667 or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
668 return $fh;
669 }
670 return;
671 };
672 }
673
674 unshift @INC, bless \%fatpacked, $class;
675 } # END OF FATPACK CODE
676
677 use strict;
678 use warnings;
679
680 use lib 'lib';
681 use CLI;
682
683 CLI->new(template => $ENV{CR_TEMPLATE}, root_dir => $ENV{CR_ROOT_DIR})->run(@ARGV);