[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 package CPANPLUS::Internals::Extract; 2 3 use strict; 4 5 use CPANPLUS::Error; 6 use CPANPLUS::Internals::Constants; 7 8 use File::Spec (); 9 use File::Basename (); 10 use Archive::Extract; 11 use IPC::Cmd qw[run]; 12 use Params::Check qw[check]; 13 use Module::Load::Conditional qw[can_load check_install]; 14 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext'; 15 16 local $Params::Check::VERBOSE = 1; 17 18 =pod 19 20 =head1 NAME 21 22 CPANPLUS::Internals::Extract 23 24 =head1 SYNOPSIS 25 26 ### for source files ### 27 $self->_gunzip( file => 'foo.gz', output => 'blah.txt' ); 28 29 ### for modules/packages ### 30 $dir = $self->_extract( module => $modobj, 31 extractdir => '/some/where' ); 32 33 =head1 DESCRIPTION 34 35 CPANPLUS::Internals::Extract extracts compressed files for CPANPLUS. 36 It can do this by either a pure perl solution (preferred) with the 37 use of C<Archive::Tar> and C<Compress::Zlib>, or with binaries, like 38 C<gzip> and C<tar>. 39 40 The flow looks like this: 41 42 $cb->_extract 43 Delegate to Archive::Extract 44 45 =head1 METHODS 46 47 =head2 $dir = _extract( module => $modobj, [perl => '/path/to/perl', extractdir => '/path/to/extract/to', prefer_bin => BOOL, verbose => BOOL, force => BOOL] ) 48 49 C<_extract> will take a module object and extract it to C<extractdir> 50 if provided, or the default location which is obtained from your 51 config. 52 53 The file name is obtained by looking at C<< $modobj->status->fetch >> 54 and will be parsed to see if it's a tar or zip archive. 55 56 If it's a zip archive, C<__unzip> will be called, otherwise C<__untar> 57 will be called. In the unlikely event the file is of neither format, 58 an error will be thrown. 59 60 C<_extract> takes the following options: 61 62 =over 4 63 64 =item module 65 66 A C<CPANPLUS::Module> object. This is required. 67 68 =item extractdir 69 70 The directory to extract the archive to. By default this looks 71 something like: 72 /CPANPLUS_BASE/PERL_VERSION/BUILD/MODULE_NAME 73 74 =item prefer_bin 75 76 A flag indicating whether you prefer a pure perl solution, ie 77 C<Archive::Tar> or C<Archive::Zip> respectively, or a binary solution 78 like C<unzip> and C<tar>. 79 80 =item perl 81 82 The path to the perl executable to use for any perl calls. Also used 83 to determine the build version directory for extraction. 84 85 =item verbose 86 87 Specifies whether to be verbose or not. Defaults to your corresponding 88 config entry. 89 90 =item force 91 92 Specifies whether to force the extraction or not. Defaults to your 93 corresponding config entry. 94 95 =back 96 97 All other options are passed on verbatim to C<__unzip> or C<__untar>. 98 99 Returns the directory the file was extracted to on success and false 100 on failure. 101 102 =cut 103 104 sub _extract { 105 my $self = shift; 106 my $conf = $self->configure_object; 107 my %hash = @_; 108 109 local $Params::Check::ALLOW_UNKNOWN = 1; 110 111 my( $mod, $verbose, $force ); 112 my $tmpl = { 113 force => { default => $conf->get_conf('force'), 114 store => \$force }, 115 verbose => { default => $conf->get_conf('verbose'), 116 store => \$verbose }, 117 prefer_bin => { default => $conf->get_conf('prefer_bin') }, 118 extractdir => { default => $conf->get_conf('extractdir') }, 119 module => { required => 1, allow => IS_MODOBJ, store => \$mod }, 120 perl => { default => $^X }, 121 }; 122 123 my $args = check( $tmpl, \%hash ) or return; 124 125 ### did we already extract it ? ### 126 my $loc = $mod->status->extract(); 127 128 if( $loc && !$force ) { 129 msg(loc("Already extracted '%1' to '%2'. ". 130 "Won't extract again without force", 131 $mod->module, $loc), $verbose); 132 return $loc; 133 } 134 135 ### did we already fetch the file? ### 136 my $file = $mod->status->fetch(); 137 unless( -s $file ) { 138 error( loc( "File '%1' has zero size: cannot extract", $file ) ); 139 return; 140 } 141 142 ### the dir to extract to ### 143 my $to = $args->{'extractdir'} || 144 File::Spec->catdir( 145 $conf->get_conf('base'), 146 $self->_perl_version( perl => $args->{'perl'} ), 147 $conf->_get_build('moddir'), 148 ); 149 150 ### delegate to Archive::Extract ### 151 ### set up some flags for archive::extract ### 152 local $Archive::Extract::PREFER_BIN = $args->{'prefer_bin'}; 153 local $Archive::Extract::DEBUG = $conf->get_conf('debug'); 154 local $Archive::Extract::WARN = $verbose; 155 156 my $ae = Archive::Extract->new( archive => $file ); 157 158 unless( $ae->extract( to => $to ) ) { 159 error( loc( "Unable to extract '%1' to '%2': %3", 160 $file, $to, $ae->error ) ); 161 return; 162 } 163 164 ### if ->files is not filled, we dont know what the hell was 165 ### extracted.. try to offer a suggestion and bail :( 166 unless ( $ae->files ) { 167 error( loc( "'%1' was not able to determine extracted ". 168 "files from the archive. Instal '%2' and ensure ". 169 "it works properly and try again", 170 $ae->is_zip ? 'Archive::Zip' : 'Archive::Tar' ) ); 171 return; 172 } 173 174 175 ### print out what files we extracted ### 176 msg(loc("Extracted '%1'",$_),$verbose) for @{$ae->files}; 177 178 ### set them all to be +w for the owner, so we don't get permission 179 ### denied for overwriting files that are just +r 180 181 ### this is to rigurous -- just change to +w for the owner [cpan #13358] 182 #chmod 0755, map { File::Spec->rel2abs( File::Spec->catdir($to, $_) ) } 183 # @{$ae->files}; 184 185 for my $file ( @{$ae->files} ) { 186 my $path = File::Spec->rel2abs( File::Spec->catfile($to, $file) ); 187 188 $self->_mode_plus_w( file => $path ); 189 } 190 191 ### check the return value for the extracted path ### 192 ### Make an educated guess if we didn't get an extract_path 193 ### back 194 ### XXX apparently some people make their own dists and they 195 ### pack up '.' which means the leading directory is '.' 196 ### and only the second directory is the actual module directory 197 ### so, we'll have to check if our educated guess exists first, 198 ### then see if the extract path works.. and if nothing works... 199 ### well, then we really don't know. 200 201 my $dir; 202 for my $try ( 203 File::Spec->rel2abs( 204 ### _safe_path must be called before catdir because catdir on 205 ### VMS currently will not handle the extra dots in the directories. 206 File::Spec->catdir( $self->_safe_path( path => $to ) , 207 $self->_safe_path( path => 208 $mod->package_name .'-'. 209 $mod->package_version 210 ) ) ) , 211 File::Spec->rel2abs( $ae->extract_path ), 212 ) { 213 ($dir = $try) && last if -d $try; 214 } 215 216 ### test if the dir exists ### 217 unless( $dir && -d $dir ) { 218 error(loc("Unable to determine extract dir for '%1'",$mod->module)); 219 return; 220 221 } else { 222 msg(loc("Extracted '%1' to '%2'", $mod->module, $dir), $verbose); 223 224 ### register where we extracted the files to, 225 ### also store what files were extracted 226 $mod->status->extract( $dir ); 227 $mod->status->files( $ae->files ); 228 } 229 230 ### also, figure out what kind of install we're dealing with ### 231 $mod->get_installer_type(); 232 233 return $mod->status->extract(); 234 } 235 236 1; 237 238 # Local variables: 239 # c-indentation-style: bsd 240 # c-basic-offset: 4 241 # indent-tabs-mode: nil 242 # End: 243 # vim: expandtab shiftwidth=4:
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |