X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Flocal%2Flib.pm;h=1153400154e60dacfed58d22e9689c80b5135970;hb=d8b2311a96dc5d2ebc189193515b1fcc4893274c;hp=9ac0a7571c8f41a89b96544a8f54de8129f11c27;hpb=93b577b582750b1e84d1bfaf916e2d0f5ef9d0ba;p=p5sagit%2Flocal-lib.git diff --git a/lib/local/lib.pm b/lib/local/lib.pm index 9ac0a75..1153400 100644 --- a/lib/local/lib.pm +++ b/lib/local/lib.pm @@ -3,14 +3,12 @@ use warnings; package local::lib; -use 5.008001; # probably works with earlier versions but I'm not supporting them - # (patches would, of course, be welcome) +use 5.006; use File::Spec (); -use File::Path (); use Config; -our $VERSION = '1.008023'; # 1.8.23 +our $VERSION = '1.008026'; # 1.8.26 $VERSION = eval $VERSION; our @KNOWN_FLAGS = qw(--self-contained --deactivate --deactivate-all); @@ -68,11 +66,6 @@ DEATH $arg_store{path} = $class->resolve_path($arg_store{path}); $class->setup_local_lib_for($arg_store{path}, $deactivating); - - for (@INC) { # Untaint @INC - next if ref; # Skip entry if it is an ARRAY, CODE, blessed, etc. - m/(.*)/ and $_ = $1; - } } sub pipeline; @@ -154,25 +147,13 @@ sub resolve_home_path { my ($class, $path) = @_; return $path unless ($path =~ /^~/); my ($user) = ($path =~ /^~([^\/]+)/); # can assume ^~ so undef for 'us' - my $tried_file_homedir; my $homedir = do { - if (eval { require File::HomeDir } && $File::HomeDir::VERSION >= 0.65) { - $tried_file_homedir = 1; - if (defined $user) { - File::HomeDir->users_home($user); - } else { - File::HomeDir->my_home; - } - } else { - if (defined $user) { - (getpwnam $user)[7]; - } else { - if (defined $ENV{HOME}) { - $ENV{HOME}; - } else { - (getpwuid $<)[7]; - } - } + if (!defined $user && defined $ENV{HOME}) { + $ENV{HOME} + } + else { + require File::Glob; + File::Glob::bsd_glob("~$user", File::Glob::GLOB_TILDE()); } }; unless (defined $homedir) { @@ -180,7 +161,6 @@ sub resolve_home_path { Carp::croak( "Couldn't resolve homedir for " .(defined $user ? $user : 'current user') - .($tried_file_homedir ? '' : ' - consider installing File::HomeDir') ); } $path =~ s/^~[^\/]*/$homedir/; @@ -209,7 +189,8 @@ sub setup_local_lib_for { my $interpolate = LITERAL_ENV; my @active_lls = $class->active_paths; - $class->ensure_dir_structure_for($path); + $class->ensure_dir_structure_for($path) + unless $deactivating; # On Win32 directories often contain spaces. But some parts of the CPAN # toolchain don't like that. To avoid this, GetShortPathName() gives us @@ -218,7 +199,7 @@ sub setup_local_lib_for { $path = Win32::GetShortPathName($path) if $^O eq 'MSWin32'; if (! $deactivating) { - if (@active_lls && $active_lls[-1] eq $path) { + if (@active_lls && $active_lls[0] eq $path) { exit 0 if $0 eq '-'; return; # Asked to add what's already at the top of the stack } elsif (grep { $_ eq $path} @active_lls) { @@ -268,10 +249,30 @@ sub ensure_dir_structure_for { unless (-d $path) { warn "Attempting to create directory ${path}\n"; } - File::Path::mkpath($path); - return + require File::Basename; + my @dirs; + while(!-d $path) { + push @dirs, $path; + $path = File::Basename::dirname($path); + } + mkdir $_ for reverse @dirs; + return; } +=begin testing + +#:: test classmethod + +File::Path::rmtree('t/var/splat'); + +$c->ensure_dir_structure_for('t/var/splat'); + +ok(-d 't/var/splat'); + +=end testing + +=cut + sub guess_shelltype { my $shellbin = 'sh'; if(defined $ENV{'SHELL'}) { @@ -345,7 +346,7 @@ sub build_bourne_env_declaration { sub build_csh_env_declaration { my $class = shift; my($name, $value) = @_; - return defined($value) ? qq{setenv ${name} "${value}"\n} : qq{unsetenv ${name}\n}; + return defined($value) ? qq{setenv ${name} "${value}";\n} : qq{unsetenv ${name};\n}; } sub build_win32_env_declaration { @@ -363,9 +364,9 @@ sub setup_env_hash_for { sub build_environment_vars_for { my ($class, $path, $deactivating, $interpolate) = @_; - if ($deactivating == DEACTIVATE_ONE) { + if ($deactivating && $deactivating == DEACTIVATE_ONE) { return $class->build_deactivate_environment_vars_for($path, $interpolate); - } elsif ($deactivating == DEACTIVATE_ALL) { + } elsif ($deactivating && $deactivating == DEACTIVATE_ALL) { return $class->build_deact_all_environment_vars_for($path, $interpolate); } else { return $class->build_activate_environment_vars_for($path, $interpolate); @@ -421,11 +422,10 @@ sub build_activate_environment_vars_for { PERL_LOCAL_LIB_ROOT => _env_list_value( { interpolate => $interpolate, exists => 0, empty => '' }, - \'PERL_LOCAL_LIB_ROOT', $path, + \'PERL_LOCAL_LIB_ROOT', ), - PERL_MB_OPT => "--install_base " . _mb_escape_path($path), - PERL_MM_OPT => "INSTALL_BASE=" . _mm_escape_path($path), + $class->installer_options_for($path), PERL5LIB => _env_list_value( { interpolate => $interpolate, exists => 0, empty => '' }, @@ -480,7 +480,6 @@ sub build_deactivate_environment_vars_for { } my $perl_path = $class->install_base_perl_path($path); - my $arch_path = $class->install_base_arch_path($path); my $bin_path = $class->install_base_bin_path($path); @@ -495,7 +494,7 @@ sub build_deactivate_environment_vars_for { { exists => 0, filter => sub { - $_ ne $perl_path && $_ ne $arch_path + $_ ne $perl_path }, }, \'PERL5LIB', @@ -511,15 +510,23 @@ sub build_deactivate_environment_vars_for { # If removing ourselves from the "top of the stack", set install paths to # correspond with the new top of stack. - if ($active_lls[-1] eq $path) { - my $new_top = $active_lls[-2]; - $env{PERL_MB_OPT} = defined($new_top) ? "--install_base "._mb_escape_path($new_top) : undef; - $env{PERL_MM_OPT} = defined($new_top) ? "INSTALL_BASE="._mm_escape_path($new_top) : undef; + if ($active_lls[0] eq $path) { + my $new_top = $active_lls[1]; + my %opts = $class->installer_options_for($new_top); + $env{keys %opts} = values %opts; } return %env; } +sub installer_options_for { + my ($class, $path) = @_; + return ( + PERL_MM_OPT => defined $path ? "INSTALL_BASE="._mm_escape_path($path) : undef, + PERL_MB_OPT => defined $path ? "--install_base "._mb_escape_path($path) : undef, + ) +} + sub build_deact_all_environment_vars_for { my ($class, $path, $interpolate) = @_; @@ -527,7 +534,6 @@ sub build_deact_all_environment_vars_for { my %perl_paths = map { ( $class->install_base_perl_path($_) => 1, - $class->install_base_arch_path($_) => 1 ) } @active_lls; my %bin_paths = map { ( $class->install_base_bin_path($_) => 1, @@ -560,17 +566,8 @@ sub build_deact_all_environment_vars_for { return %env; } -=begin testing - -#:: test classmethod - -File::Path::rmtree('t/var/splat'); - -$c->ensure_dir_structure_for('t/var/splat'); - -ok(-d 't/var/splat'); - -=end testing +1; +__END__ =encoding utf8 @@ -599,7 +596,7 @@ From the shell - $ perl -Mlocal::lib export PERL_MB_OPT='--install_base /home/username/perl5' export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5' - export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5' + export PERL5LIB="/home/username/perl5/lib/perl5" export PATH="/home/username/perl5/bin:$PATH" =head2 The bootstrapping technique @@ -653,8 +650,9 @@ If you are using C shell, you can do this as follows: /bin/csh perl -I$HOME/perl5/lib/perl5 -Mlocal::lib >> ~/.cshrc -If you passed to bootstrap a directory other than default, you also need to give that as -import parameter to the call of the local::lib module like this way: +If you passed to bootstrap a directory other than default, you also need to +give that as import parameter to the call of the local::lib module like this +way: echo 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' >>~/.bashrc @@ -721,7 +719,7 @@ C, you can use this: C:\>perl -Mlocal::lib set PERL_MB_OPT=--install_base C:\DOCUME~1\ADMINI~1\perl5 set PERL_MM_OPT=INSTALL_BASE=C:\DOCUME~1\ADMINI~1\perl5 - set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5;C:\DOCUME~1\ADMINI~1\perl5\lib\perl5\MSWin32-x86-multi-thread + set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5 set PATH=C:\DOCUME~1\ADMINI~1\perl5\bin;%PATH% ### To set the environment for this shell alone @@ -787,10 +785,10 @@ values: =item PATH -PATH is appended to, rather than clobbered. - =back +When possible, these will be appended to instead of overwritten entirely. + These values are then available for reference by any code after import. =head1 CREATING A SELF-CONTAINED SET OF MODULES @@ -849,7 +847,7 @@ given path as the base directory. =item Arguments: $path, $interpolate -=item Return value: \%environment_vars +=item Return value: %environment_vars =back @@ -897,21 +895,6 @@ Returns a path describing where to install the Perl modules for this local library installation. Appends the directories C and C to the given path. -=head2 install_base_arch_path - -=over 4 - -=item Arguments: $path - -=item Return value: $install_base_arch_path - -=back - -Returns a path describing where to install the architecture-specific Perl -modules for this local library installation. Based on the -L method's return value, and appends the value of -C<$Config{archname}>. - =head2 install_base_bin_path =over 4 @@ -923,8 +906,7 @@ C<$Config{archname}>. =back Returns a path describing where to install the executable programs for this -local library installation. Based on the L method's -return value, and appends the directory C. +local library installation. Appends the directory C to the given path. =head2 resolve_empty_path @@ -997,21 +979,19 @@ install UNINST=1" and local::lib if you understand these possible consequences. =over 4 -=item * The perl toolchain is unable to handle directory names with spaces in it, -so you can't put your local::lib bootstrap into a directory with spaces. What -you can do is moving your local::lib to a directory with spaces B you -installed all modules inside your local::lib bootstrap. But be aware that you -can't update or install CPAN modules after the move. +=item * Directory names with spaces in them are not well supported by the perl +toolchain and the programs it uses. Pure-perl distributions should support +spaces, but problems are more likely with dists that require compilation. A +workaround you can do is moving your local::lib to a directory with spaces +B you installed all modules inside your local::lib bootstrap. But be +aware that you can't update or install CPAN modules after the move. =item * Rather basic shell detection. Right now anything with csh in its name is assumed to be a C shell or something compatible, and everything else is assumed to be Bourne, except on Win32 systems. If the C environment variable is not set, a Bourne-compatible shell is assumed. -=item * Bootstrap is a hack and will use CPAN.pm for ExtUtils::MakeMaker even if you -have CPANPLUS installed. - -=item * Kills any existing PERL5LIB, PERL_MM_OPT or PERL_MB_OPT. +=item * Kills any existing PERL_MM_OPT or PERL_MB_OPT. =item * Should probably auto-fixup CPAN config if not already done. @@ -1021,8 +1001,8 @@ Patches very much welcome for any of the above. =over 4 -=item * On Win32 systems, does not have a way to write the created environment variables -to the registry, so that they can persist through a reboot. +=item * On Win32 systems, does not have a way to write the created environment +variables to the registry, so that they can persist through a reboot. =back @@ -1083,8 +1063,8 @@ Patches to correctly output commands for csh style shells, as well as some documentation additions, contributed by Christopher Nehren . Doc patches for a custom local::lib directory, more cleanups in the english -documentation and a L contributed by Torsten Raudssus -. +documentation and a L contributed by +Torsten Raudssus . Hans Dieter Pearcey sent in some additional tests for ensuring things will install properly, submitted a fix for the bug causing problems with @@ -1106,13 +1086,14 @@ Mark Stosberg provided the code for the now deleted Documentation patches to make win32 usage clearer by David Mertens (run4flat). -Brazilian L and minor doc patches contributed by Breno -G. de Oliveira . +Brazilian L and minor doc +patches contributed by Breno G. de Oliveira . Improvements to stacking multiple local::lib dirs and removing them from the environment later on contributed by Andrew Rodland . -Patch for Carp version mismatch contributed by Hakim Cassimally . +Patch for Carp version mismatch contributed by Hakim Cassimally +. =head1 COPYRIGHT @@ -1125,5 +1106,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - -1;