File Coverage

blib/lib/App/Build.pm
Criterion Covered Total %
statement 66 218 30.2
branch 8 90 8.8
condition 1 29 3.4
subroutine 17 32 53.1
pod 14 14 100.0
total 106 383 27.6


line stmt bran cond sub pod time code
1             package App::Build;
2              
3 5     5   1456375 use strict;
  5         17  
  5         295  
4              
5             # undo @ARGV manipulation done by App::Options, to allow Module::Build to work
6 5     5   94 my @orig_ARGV; BEGIN { @orig_ARGV = @ARGV; }
7 5     5   7382 use App::Options;
  5         83721  
  5         78  
8             @ARGV = @orig_ARGV;
9              
10 5     5   52061 use Module::Build;
  5         444806  
  5         173  
11 5     5   33 use Cwd ();
  5         11  
  5         81  
12 5     5   26 use File::Spec;
  5         11  
  5         109  
13 5     5   28 use File::Basename qw();
  5         9  
  5         81  
14 5     5   27 use File::Path qw();
  5         9  
  5         15893  
15              
16             our $VERSION = "0.74";
17             our @ISA = ("Module::Build");
18              
19             =head1 NAME
20              
21             App::Build - extends Module::Build to build/install/configure entire applications (i.e. web applications), not just modules and programs
22              
23             =head1 SYNOPSIS
24              
25             This module is used within a Build.PL script directly or
26             it can be subclassed to provide extra capabilities.
27              
28             use App::Build;
29              
30             my $build = App::Build->new (
31             dist_name => "App-Build-Foo",
32             dist_version => "1.0",
33             dist_author => "stephen.adkins\@officevision.com",
34             extra_dirs => [ "htdocs", "cgi-bin", "etc", "var" ],
35             license => "perl",
36             build_requires => {
37             "App::Build" => 0, # needed for installing the software
38             },
39             );
40            
41             $build->create_build_script;
42              
43             =head1 DESCRIPTION
44              
45             App::Build is a subclass of Module::Build, so you can use
46             it in place of Module::Build when creating your "Build.PL"
47             installation scripts.
48              
49             Module::Build is good at
50             installing perl modules and programs/scripts. Full applications
51             (i.e. web applications) need to install other files such as
52             web pages, images, CSS style sheets, javascript files,
53             CGI programs, data files, and configuration data.
54             App::Build addresses these issues.
55              
56             The vision of App::Build is to make installing entirely
57             functional perl applications (particularly web applications)
58             as easy as installing individual modules from CPAN.
59              
60             An ISP customer (or other unprivileged user)
61             who has shell access should be able to install any number
62             of available applications from CPAN simply by typing the
63             usual
64              
65             perl -MCPAN -e "install App::Build::Foo"
66              
67             and the "Foo" application is installed on his account.
68              
69             App::Build does this by implementing the following features.
70              
71             1. Distributions that use App::Build instead of Module::Build
72             can easily install files to other places, besides just
73             "lib" and "bin". e.g. "htdocs", "cgi-bin", "etc".
74             (see the "extra_dirs" argument in the example in the Synopsis
75             above)
76              
77             2. App::Build also adds a hook into the "install" action to
78             call the "configure()" method. If you are subclassing
79             App::Build, you can override this method and perform
80             customized configuration tasks.
81              
82             =head1 INCLUDED APPLICATIONS AND EXTERNAL APPLICATIONS
83              
84             Although the distribution primarily supports the deployment
85             of an application whose files are included in the distribution,
86             it also supports deployment of applications which are not
87             included or are not on CPAN at all.
88              
89             Anyone who finds a useful perl application somewhere
90             (i.e. "Foo") can write a small perl distribution called
91             App-Build-Foo and upload it to CPAN.
92             When someone uses the CPAN shell, they can install the
93             application simply by typing
94              
95             install App::Build::Foo
96              
97             Within the App-Build-Foo distribution would be a module,
98             App::Build::Foo, which would be a subclass of App::Build.
99             It would contain any specific logic necessary to download
100             and install the Foo application.
101              
102             All applications installed with App::Build (and its
103             derivatives) should conform to a set of standards (see
104             below) so that when multiple applications are installed,
105             they are integrated seamlessly and work side by side.
106              
107             =head1 APPLICATION INSTALLATION REQUIREMENTS
108              
109             The following are the requirements of all App::Build
110             installations.
111              
112             * The installation MUST be useful to ISP's (internet
113             service providers) and ASP's (application service
114             providers) such that the software is installed
115             in such a way that each customer of theirs may use
116             it without any interactions with other customers.
117              
118             * The installation SHOULD allow for multiple versions
119             even for an unprivileged user (an ISP/ASP customer).
120             This allows a user to install a new version of an
121             application and evaluate it and run it in parallel
122             with an existing version of the application.
123              
124             =head1 APPLICATION INSTALLATION STANDARDS
125              
126             The following are additional standards of all App::Build
127             installations.
128              
129             * TBD
130              
131             =head1 App::Build CONFIGURABILITY
132              
133             Since App::Build uses App::Options, App::Options makes all the
134             of the --var=value options available via the global %App::options hash.
135             App::Build however does not remove the --var=value options from @ARGV.
136              
137             This will be put to good use sometime in the future.
138              
139             =head1 FIX-UPS
140              
141             Module::Build complains if the PREFIX environment variable is
142             set. App::Build doesn't. It just ignores it.
143              
144             The CPAN shell (for some reason I don't understand) runs Build.PL
145             as "perl Build.PL Build" and this fails.
146             App::Build just throws away the "Build" so that the default "build"
147             action is invoked.
148              
149             Module::Build deprecated the PREFIX option to Makefile.PL
150             (i.e. "perl Makefile.PL PREFIX=/usr/foo"). App::Build just makes
151             the PREFIX option a synonym for "install_base", which does
152             essentially the same thing.
153              
154             =cut
155              
156             delete $ENV{PREFIX}; # Module::Build protests if this var is set
157              
158             # Enable the continued use of the PREFIX=$PREFIX option
159             # (from Makefile.PL and ExtUtils::MakeMaker) by making it
160             # an alias for the "install_base" option of Module::Build.
161              
162             ######################################################################
163             # BUILD: enhancements to "perl Build.PL"
164             ######################################################################
165              
166             =head1 METHODS
167              
168             The documentation of the methods below is not for users of the
169             App::Build module (who are writing Build.PL scripts), but for people
170             interested in the internals of how App::Build extends Module::Build.
171              
172             It is also so that I can remember what I was doing so that if the
173             internals of Module::Build change, I can maintain this code.
174              
175             =head2 new()
176              
177             We override the new() method in order to enhance the install paths.
178              
179             In the future, we may also download and unpack external perl
180             distributions.
181              
182             =cut
183              
184             sub new {
185 3     3 1 255022 my ($class, %args) = @_;
186 3         58 my $obj = $class->SUPER::new(%args);
187              
188 3 50       1346 $obj->_enhance_install_paths() if $obj->_prefix;
189 3         31 $obj->_get_supporting_software();
190              
191 3         46 return($obj);
192             }
193              
194             =head2 read_config()
195              
196             Overridden to transparently call C<_enhance_install_paths()>.
197              
198             =cut
199              
200             sub read_config {
201 0     0 1 0 my ($self) = @_;
202              
203 0         0 $self->SUPER::read_config();
204 0 0       0 $self->_enhance_install_paths() if $self->_prefix;
205             }
206              
207             =head2 install_base()
208              
209             Overridden to transparently call C<_enhance_install_paths()>.
210              
211             =cut
212              
213             sub install_base {
214 4     4 1 114 my ($self, @args) = @_;
215              
216 4         37 my $ret = $self->SUPER::install_base(@args);
217 4 50       110 $self->_enhance_install_paths() if $self->_prefix;
218              
219 4         11 return $ret;
220             }
221              
222             =head2 _get_supporting_software()
223              
224             Downloads supporting software (if necessary), unpacks it, compiles it,
225             and installs it.
226              
227             =cut
228              
229             sub _get_supporting_software {
230 3     3   16 my ($self) = @_;
231              
232 3         105 my $tag = $self->_app_tag();
233              
234 3         18 my $url = $App::options{"$tag.url"}; # check to see if there was software to download
235 3 50       52 if ($url) {
236 0         0 my $file = $App::options{"$tag.file"};
237 0 0       0 if (!$file) {
238 0         0 $file = $url;
239 0         0 $file =~ s!.*/!!;
240             }
241 0 0       0 ($file) || die "File [$tag.file] does not exist";
242              
243 0         0 my $subdir = $App::options{"$tag.subdir"};
244 0 0       0 if (!$subdir) {
245 0         0 $subdir = $file;
246 0         0 $subdir =~ s!\.tar.gz$!!;
247 0         0 $subdir =~ s!\.tgz$!!;
248             }
249 0 0       0 ($subdir) || die "Subdir [$tag.subdir] does not exist";
250              
251 0   0     0 my $archive_dir = $App::options{archive_dir} || "archive";
252 0 0       0 mkdir($archive_dir) if (! -d $archive_dir);
253              
254 0         0 my $archive = "$archive_dir/$file";
255              
256 0 0       0 (-d $archive_dir) || die "Archive Directory [$archive_dir] does not exist";
257 0 0       0 (-w $archive_dir) || die "Archive Directory [$archive_dir] not writeable";
258              
259 0         0 $self->mirror($url, $archive);
260 0         0 $self->unpack($archive, "unpack", $subdir);
261             }
262             }
263              
264             =head2 _app_tag()
265              
266             This lowercase-ifies the dist_name, removes "app-build-" from the front,
267             and returns it as the "application tag".
268             Therefore, a distribution called "App-Build-Kwiki" would have an
269             "app_tag" of "kwiki". An "app_tag" is used for looking up configuration
270             settings in the %App::options hash produced by App::Options.
271              
272             =cut
273              
274             sub _app_tag {
275 3     3   92 my ($self) = @_;
276 3         20 my $dist_name = $self->dist_name();
277 3         38 my $tag = lc($dist_name);
278 3         12 $tag =~ s/^app-build-//;
279 3         17 return($tag);
280             }
281              
282             =head2 _prefix()
283              
284             This returns the "install_base" property if it was supplied on the command
285             line. i.e.
286              
287             perl Build.PL install_base=/usr/mycompany/prod
288              
289             or (synonymously) ...
290              
291             perl Build.PL PREFIX=/usr/mycompany/prod
292              
293             If the install_base was not supplied, the "prefix" out of perl's own
294             Config.pm is returned. So if perl is installed in "/usr/local/bin", then
295             "/usr/local" is returned.
296             If perl is installed in "/usr/bin", then "/usr" is returned.
297              
298             =cut
299              
300             sub _prefix {
301 7     7   29 my ($self) = @_;
302 7   33     116 my $prefix = $self->{properties}{install_base} || $self->{config}{prefix};
303 7         47 return($prefix);
304             }
305              
306             =head2 _enhance_install_paths()
307              
308             The install_sets (core, site, vendor) as set from values in perl's own
309             Config.pm are enhanced to include the absolute directories in which
310             the extra_dirs will be installed.
311              
312             =cut
313              
314             sub _enhance_install_paths {
315 0     0   0 my ($self) = @_;
316 0         0 my $properties = $self->{properties};
317 0         0 my $install_sets = $properties->{install_sets};
318 0         0 my @extra_dirs = $self->_get_extra_dirs();
319 0         0 my $prefix = $self->_prefix();
320 0         0 my $tag = $self->_app_tag();
321 0         0 my ($path);
322 0         0 foreach my $dir (@extra_dirs) {
323 0   0     0 $path = $App::options{"$tag.$dir.dir"} || File::Spec->catdir($prefix, $dir);
324 0         0 $install_sets->{core}{$dir} = $path;
325 0         0 $install_sets->{site}{$dir} = $path;
326 0         0 $install_sets->{vendor}{$dir} = $path;
327             }
328             }
329              
330             ######################################################################
331             # BUILD: enhancements to "./Build"
332             ######################################################################
333              
334             =head2 ACTION_code()
335              
336             We override ACTION_code() to copy additional directories of files
337             needed to install the application.
338              
339             When you invoke "./Build", the method $self->ACTION_build() gets
340             called on this object. This, in turn, calls $self->ACTION_code()
341             and $self->ACTION_docs(). Each of these methods copies files into
342             the "blib" subdirectory in preparation for installation.
343              
344             =cut
345              
346             sub ACTION_code {
347 0     0 1 0 my ($self) = @_;
348 0         0 $self->SUPER::ACTION_code(); # call this first (creates "blib" dir if necessary)
349 0         0 $self->process_app_files(); # NEW. call this to copy "extra_dirs" to "blib"
350             }
351              
352             =head2 _added_to_INC()
353              
354             We override this method to ensure that "lib" (libraries to be installed)
355             is added to the front of @INC.
356             This is because we often want to use the (latest) enclosed module as
357             the installing module, even if it has already been installed.
358              
359             =cut
360              
361             sub _added_to_INC {
362 3     3   1014 my $self = shift;
363 3         9 my %seen;
364 3         40 $seen{$_}++ foreach $self->_default_INC;
365 3         33853 unshift(@INC,"lib");
366 3         228 return grep !$seen{$_}++, @INC;
367             }
368              
369             =head2 _get_extra_dirs()
370              
371             Gets the list of extra_dirs to be installed.
372              
373             The extra_dirs may be specified in the Build.PL in
374             a variety of ways.
375             It can be a scalar (comma-separated list of directories),
376             an array ref of directories, or a hash ref where the
377             keys are the directories.
378              
379             If extra_dirs is specified with a hash ref, the hash values
380             are hashrefs of attributes. i.e.
381              
382             extra_dirs => {
383             var => {
384             dest_dir => "var",
385             },
386             htdocs => {
387             dest_dir => "htdocs",
388             },
389             "cgi-bin" => { # any dir ending in "bin" contains executable scripts
390             dest_dir => "cgi-bin",
391             },
392             support => {
393             dest_dir => "support",
394             executable => 1, # treat contents as executable scripts
395             },
396             },
397              
398             So far, only the "dest_dir" attribute is defined. The "dest_dir" attribute
399             can be overridden using the "--install_path" parameter.
400              
401             =cut
402              
403             sub _get_extra_dirs {
404 0     0   0 my ($self) = @_;
405 0         0 my $properties = $self->{properties};
406 0         0 my @extra_dirs = ();
407 0 0       0 if ($properties->{extra_dirs}) {
408 0 0       0 if (ref($properties->{extra_dirs}) eq "ARRAY") {
    0          
    0          
409 0         0 @extra_dirs = @{$properties->{extra_dirs}};
  0         0  
410             }
411             elsif (ref($properties->{extra_dirs}) eq "HASH") {
412 0         0 @extra_dirs = (sort keys %{$properties->{extra_dirs}});
  0         0  
413             }
414             elsif (ref($properties->{extra_dirs})) {
415 0         0 die "extra_dirs can be a scalar, array ref, or hash ref, but not " . ref($properties->{extra_dirs});
416             }
417             else {
418 0         0 @extra_dirs = split(/,/,$properties->{extra_dirs});
419             }
420             }
421 0         0 return(@extra_dirs);
422             }
423              
424             =head2 _get_extra_dirs_attributes()
425              
426             Gets the hash of all extra_dirs attributes.
427              
428             =cut
429              
430             sub _get_extra_dirs_attributes {
431 0     0   0 my ($self) = @_;
432 0         0 my $properties = $self->{properties};
433 0         0 my @extra_dirs = ();
434 0         0 my ($extra_dirs);
435 0 0       0 if ($properties->{extra_dirs}) {
436 0 0       0 if (ref($properties->{extra_dirs}) eq "ARRAY") {
    0          
    0          
437 0         0 @extra_dirs = @{$properties->{extra_dirs}};
  0         0  
438 0         0 $extra_dirs = { map { $_ => { dest_dir => $_ } } @extra_dirs };
  0         0  
439             }
440             elsif (ref($properties->{extra_dirs}) eq "HASH") {
441 0         0 @extra_dirs = (sort keys %{$properties->{extra_dirs}});
  0         0  
442 0         0 $extra_dirs = $properties->{extra_dirs};
443             }
444             elsif (ref($properties->{extra_dirs})) {
445 0         0 die "extra_dirs can be a scalar, array ref, or hash ref, but not " . ref($properties->{extra_dirs});
446             }
447             else {
448 0         0 @extra_dirs = split(/,/,$properties->{extra_dirs});
449 0         0 $extra_dirs = { map { $_ => { dest_dir => $_ } } @extra_dirs };
  0         0  
450             }
451 0         0 foreach my $dir (@extra_dirs) {
452 0 0       0 $extra_dirs->{$dir}{dest_dir} = $self->install_path($dir)
453             if $self->install_path($dir);
454 0 0       0 $extra_dirs->{$dir}{dest_dir} = $dir if (!$extra_dirs->{$dir}{dest_dir});
455             }
456             }
457 0         0 return($extra_dirs);
458             }
459              
460             =head2 process_app_files()
461              
462             During "./Build" (which calls ACTION_code()), the process_app_files()
463             method copies files from the extra_dirs to their appropriate
464             locations under "blib".
465              
466             =cut
467              
468             sub process_app_files {
469 0     0 1 0 my ($self) = @_;
470 0         0 my ($path, $files);
471              
472 0         0 my @extra_dirs = $self->_get_extra_dirs();
473 0         0 my $extra_dirs = $self->_get_extra_dirs_attributes();
474              
475 0         0 my $blib = $self->blib;
476 0         0 my ($contains_executables, $result, $target_file);
477 0         0 foreach my $dir (@extra_dirs) {
478 0 0       0 if (-d $dir) {
479 0         0 $contains_executables = $extra_dirs->{$dir}{executable};
480 0 0       0 $contains_executables = ($dir =~ /bin$/) ? 1 : 0 if (!defined $contains_executables);
    0          
481 0         0 $path = File::Spec->catfile($blib, $dir),
482             File::Path::mkpath($path);
483 0         0 $files = $self->_find_all_files($dir);
484 0         0 my ($should_be_executable);
485 0         0 while (my ($file, $dest) = each %$files) {
486 0         0 $target_file = File::Spec->catfile($blib, $dest);
487 0   0     0 $result = $self->copy_if_modified(from => $file, to => $target_file) || "";
488 0 0 0     0 if ($result && $contains_executables) {
489 0         0 $self->fix_shebang_line($result);
490 0 0       0 $self->make_executable($result)
491             if $self->_should_be_executable($result);
492             }
493             }
494             }
495             }
496             }
497              
498             sub _should_be_executable {
499 0     0   0 my ($self, $file) = @_;
500              
501             # copied from Module::Build::Base::fix_shebang_line
502 0 0       0 my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!";
503 0         0 local $/ = "\n";
504 0         0 chomp(my $line = <$FIXIN>);
505 0 0       0 if ($line =~ /^\s*\#!\s*/) {
506 0         0 return 1;
507             } else {
508 0         0 return 0;
509             }
510             }
511              
512             =head2 _find_all_files()
513              
514             This is used by process_app_files() to get the list of files under "extra_dirs"
515             to copy to "blib".
516              
517             =cut
518              
519             sub _find_all_files {
520 0     0   0 my ($self, $dir) = @_;
521 0 0       0 return {} unless -d $dir;
522 0     0   0 return { map { $_, $_ } @{ $self->rscan_dir($dir, sub { -f $_ }) } };
  0         0  
  0         0  
  0         0  
523             }
524              
525             =head2 rscan_dir()
526              
527             Don't include CVS, RCS, and SVN (*/.svn/*) files.
528              
529             =cut
530              
531             sub rscan_dir {
532 3     3 1 259721 my ($self, $dir, $pattern) = @_;
533 3         97 my $files = $self->SUPER::rscan_dir($dir, $pattern);
534 3         803 my @files = grep(!/[\/\\](CVS|RCS|\.svn)[\/\\]/, @$files);
535 3         29 return \@files;
536             }
537              
538             ######################################################################
539             # INSTALL: enhancements to "./Build install"
540             ######################################################################
541              
542             =head2 packlist()
543              
544             This creates the name of the "packlist" file that needs to be
545             written with the list of all of the files that get installed.
546              
547             =cut
548              
549             sub packlist {
550 2     2 1 25 my ($self) = @_;
551             # Write the packlist into the same place as ExtUtils::MakeMaker.
552 2         43 my $archdir = $self->install_destination('arch');
553 2 100       2467 my @ext = $self->module_name ? split /::/, $self->module_name :
554             $self->dist_name;
555 2         93 my $packlist = File::Spec->catfile($archdir, 'auto', @ext, '.packlist');
556 2         23 return($packlist);
557             }
558              
559             =head2 install_map()
560              
561             This method is only overridden in order to put in the fix so
562             that it creates a .packlist based on dist_name if the module_name
563             is not specified.
564              
565             =cut
566              
567             sub install_map {
568 0     0 1 0 my ($self, $blib) = @_;
569 0   0     0 $blib ||= $self->blib;
570              
571 0         0 my %map;
572 0         0 foreach my $type ($self->install_types) {
573 0         0 my $localdir = File::Spec->catdir( $blib, $type );
574 0 0       0 next unless -e $localdir;
575              
576 0 0       0 if (my $dest = $self->install_destination($type)) {
577             # thins alters the behavious of Module::Build, and
578             # looks into the implementation
579 0 0 0     0 if ( $self->install_path($type)
580             && !File::Spec->file_name_is_absolute($dest)) {
581 0         0 $dest = File::Spec->catdir( $self->_prefix, $dest );
582             }
583 0         0 $map{$localdir} = $dest;
584             } else {
585             # Platforms like Win32, MacOS, etc. may not build man pages
586 0 0       0 die "Can't figure out where to install things of type '$type'"
587             unless $type =~ /^(lib|bin)doc$/;
588             }
589             }
590              
591 0         0 my $extra_dirs_attrs = $self->_get_extra_dirs_attributes();
592 0         0 foreach my $dir ( $self->_get_extra_dirs() ) {
593 0         0 my $dest = $extra_dirs_attrs->{$dir}{dest_dir};
594 0 0       0 if (!File::Spec->file_name_is_absolute($dest)) {
595 0         0 $dest = File::Spec->catdir( $self->_prefix, $dest );
596             }
597 0         0 $map{File::Spec->catdir( $blib, $dir )} = $dest;
598             }
599              
600 0 0       0 if ($self->create_packlist) {
601 0         0 $map{write} = $self->packlist();
602             }
603              
604 0 0 0     0 if (length(my $destdir = $self->{properties}{destdir} || '')) {
605 0         0 foreach (keys %map) {
606             # Need to remove volume from $map{$_} using splitpath, or else
607             # we'll create something crazy like C:\Foo\Bar\E:\Baz\Quux
608 0         0 my ($volume, $path) = File::Spec->splitpath( $map{$_}, 1 );
609 0         0 $map{$_} = File::Spec->catdir($destdir, $path);
610             }
611             }
612              
613 0         0 $map{read} = ''; # To keep ExtUtils::Install quiet
614              
615 0         0 return \%map;
616             }
617              
618             =head2 has_config_data()
619              
620             No. We're not using config data.
621             Always return FALSE.
622              
623             =cut
624              
625             sub has_config_data {
626 0     0 1 0 my ($self) = @_;
627 0         0 return(0);
628             }
629              
630             =head2 ACTION_install()
631              
632             This method is overridden to put in the configure() hook so that
633             a module which extends App::Build can implement the configure()
634             method. Then the configure() method will run when
635             "./Build install" is invoked.
636              
637             =cut
638              
639             sub ACTION_install {
640 0     0 1 0 my ($self) = @_;
641 0         0 require ExtUtils::Install;
642 0         0 $self->depends_on('build');
643 0         0 my $map = $self->install_map;
644 0   0     0 ExtUtils::Install::install($map, 1, 0, $self->{args}{uninst}||0);
645 0         0 $self->perllocal_install();
646 0         0 $self->configure();
647             }
648              
649             =head2 perllocal_install()
650              
651             This method should be modelled after ExtUtils::Command::MM::perllocal_install
652             so that it writes the same information at MakeMaker does.
653              
654             It currently is a stub, waiting to be implemented
655              
656             =cut
657              
658             sub perllocal_install {
659 0     0 1 0 my ($self) = @_;
660             # Not yet implemented.
661             }
662              
663             =head2 configure()
664              
665             Do nothing. This method is a hook that can be overridden by a
666             subclass of App::Build.
667             The idea is that after installing files, you might need to run additional
668             code to configure the application.
669              
670             =cut
671              
672             sub configure {
673 0     0 1 0 my ($self) = @_;
674             # Do nothing. This is a hook for overriding in a subclass.
675             }
676              
677             =head2 mirror()
678              
679             * Signature: $build->mirror($url, $file);
680             * Param: $url string
681             * Param: $file string
682              
683             TODO: Should be rewritten to use cross-platform, pure-perl.
684              
685             =cut
686              
687             sub mirror {
688 2     2 1 6202 my ($self, $url, $file) = @_;
689 2 100       100 if (! -f $file) {
690 1         76 $self->log_info("Mirroring $url to $file\n");
691 1         83 require File::Fetch;
692 1         102 my $ff = File::Fetch->new(uri => $url);
693 1         5395 my $where = $ff->fetch(to => File::Basename::dirname($file));
694 1 50       240321 if($where) {
695 1         93 rename($where, $file);
696             }
697             }
698             else {
699 1         46 $self->log_info("Mirrored file $file up to date\n");
700             }
701             }
702              
703             =head2 unpack()
704              
705             * Signature: $build->unpack($archive_file, $directory, $subdir);
706             * Param: $archive_file string
707             * Param: $directory string
708             * Param: $subdir string
709              
710             TODO: Should be rewritten to use cross-platform, pure-perl.
711              
712             =cut
713              
714             sub unpack {
715 0     0 1   my ($self, $archive_file, $directory, $subdir) = @_;
716 0           require Archive::Extract;
717 0   0       $directory ||= "$App::options{install_prefix}/src";
718 0 0         mkdir($directory) if (! -d $directory);
719 0 0         die "Directory $directory does not exist and can't be created" if (! -d $directory);
720              
721 0 0         if (! File::Spec->file_name_is_absolute($archive_file)) {
722 0           $archive_file = File::Spec->catfile(Cwd::getcwd(), $archive_file);
723             }
724 0           $subdir = File::Spec->catdir($directory, $subdir);
725              
726 0 0 0       if ($subdir && -d $subdir) {
727 0           $self->log_info("Removing preexisting directory $subdir ...\n");
728 0           File::Path::rmtree($subdir);
729             }
730 0           $self->log_info("Unpacking $archive_file ...\n");
731              
732 0           my $ae = Archive::Extract->new(archive => $archive_file);
733 0 0         my $ok = $ae->extract(to => $directory) or die $ae->error;
734              
735 0 0         die "Subdirectory $subdir not created" if (! -d $subdir);
736             }
737              
738             =head1 ACKNOWLEDGEMENTS
739              
740             * Author: Stephen Adkins
741             * Maintainer: Mattia Barbon
742              
743             =head1 LICENSE
744              
745             This program is free software; you can redistribute it and/or
746             modify it under the same terms as Perl itself.
747              
748             =head1 SOURCES
749              
750             The latest sources can be found on GitHub at
751             L
752              
753             =head1 SEE ALSO
754              
755             =cut
756              
757             1;
758              
759             __END__