File Coverage

blib/lib/Alien/Build/Plugin/Fetch/NetFTP.pm
Criterion Covered Total %
statement 29 86 33.7
branch 2 42 4.7
condition 2 8 25.0
subroutine 8 10 80.0
pod 1 1 100.0
total 42 147 28.5


line stmt bran cond sub pod time code
1             package Alien::Build::Plugin::Fetch::NetFTP;
2              
3 2     2   1320 use strict;
  2         4  
  2         53  
4 2     2   9 use warnings;
  2         4  
  2         46  
5 2     2   39 use 5.008004;
  2         5  
6 2     2   344 use Alien::Build::Plugin;
  2         6  
  2         46  
7 2     2   12 use Carp ();
  2         4  
  2         31  
8 2     2   8 use File::Temp ();
  2         4  
  2         31  
9 2     2   10 use Path::Tiny qw( path );
  2         4  
  2         1604  
10              
11             # ABSTRACT: Plugin for fetching files using Net::FTP
12             our $VERSION = '2.47'; # VERSION
13              
14              
15             has '+url' => '';
16              
17              
18             has ssl => 0;
19              
20              
21             has passive => 0;
22              
23             sub init
24             {
25 3     3 1 17 my($self, $meta) = @_;
26              
27 3   66     9 $meta->prop->{start_url} ||= $self->url;
28 3         7 $self->url($meta->prop->{start_url});
29 3 50       5 $self->url || Carp::croak('url is a required property');
30              
31 3         10 $meta->add_requires('share' => 'Net::FTP' => 0 );
32 3         8 $meta->add_requires('share' => 'URI' => 0 );
33 3 50       7 $meta->add_requires('share' => 'Alien::Build::Plugin::Fetch::NetFTP' => '0.61')
34             if $self->passive;
35              
36             $meta->register_hook( fetch => sub {
37 0     0   0 my($build, $url, %options) = @_;
38 0   0     0 $url ||= $self->url;
39              
40 0 0       0 $build->log("plugin Fetch::NetFTP does not support http_headers option") if $options{http_headers};
41              
42 0         0 $url = URI->new($url);
43              
44 0 0       0 die "Fetch::NetFTP does not support @{[ $url->scheme ]}"
  0         0  
45             unless $url->scheme eq 'ftp';
46              
47 0 0       0 $build->log("trying passive mode FTP first") if $self->passive;
48 0         0 my $ftp = _ftp_connect($url, $self->passive);
49              
50 0         0 my $path = $url->path;
51              
52 0 0       0 unless($path =~ m!/$!)
53             {
54 0         0 my(@parts) = split /\//, $path;
55 0         0 my $filename = pop @parts;
56 0         0 my $dir = join '/', @parts;
57              
58 0         0 my $path = eval {
59 0 0       0 $ftp->cwd($dir) or die;
60 0         0 my $tdir = File::Temp::tempdir( CLEANUP => 1);
61 0         0 my $path = path("$tdir/$filename")->stringify;
62              
63 0 0       0 unless(eval { $ftp->get($filename, $path) }) # NAT problem? try to use passive mode
  0         0  
64             {
65 0         0 $ftp->quit;
66              
67 0 0       0 $build->log("switching to @{[ $self->passive ? 'active' : 'passive' ]} mode");
  0         0  
68 0         0 $ftp = _ftp_connect($url, !$self->passive);
69              
70 0 0       0 $ftp->cwd($dir) or die;
71              
72 0 0       0 $ftp->get($filename, $path) or die;
73             }
74              
75 0         0 $path;
76             };
77              
78 0 0       0 if(defined $path)
79             {
80             return {
81 0         0 type => 'file',
82             filename => $filename,
83             path => $path,
84             };
85             }
86              
87 0         0 $path .= "/";
88             }
89              
90 0         0 $ftp->quit;
91 0         0 $ftp = _ftp_connect($url, $self->passive);
92 0 0       0 $ftp->cwd($path) or die "unable to fetch $url as either a directory or file";
93              
94 0         0 my $list = eval { $ftp->ls };
  0         0  
95 0 0       0 unless(defined $list) # NAT problem? try to use passive mode
96             {
97 0         0 $ftp->quit;
98              
99 0 0       0 $build->log("switching to @{[ $self->passive ? 'active' : 'passive' ]} mode");
  0         0  
100 0         0 $ftp = _ftp_connect($url, !$self->passive);
101              
102 0 0       0 $ftp->cwd($path) or die "unable to fetch $url as either a directory or file";
103              
104 0         0 $list = $ftp->ls;
105              
106 0 0       0 die "cannot list directory $path on $url" unless defined $list;
107             }
108              
109 0 0       0 die "no files found at $url" unless @$list;
110              
111 0 0       0 $path .= '/' unless $path =~ /\/$/;
112              
113             return {
114             type => 'list',
115             list => [
116             map {
117 0         0 my $filename = $_;
  0         0  
118 0         0 my $furl = $url->clone;
119 0         0 $furl->path($path . $filename);
120 0         0 my %h = (
121             filename => $filename,
122             url => $furl->as_string,
123             );
124 0         0 \%h;
125             } sort @$list,
126             ],
127             };
128              
129 3         28 });
130              
131 3         4 $self;
132             }
133              
134             sub _ftp_connect {
135 0     0     my $url = shift;
136 0   0       my $is_passive = shift || 0;
137              
138 0 0         my $ftp = Net::FTP->new(
139             $url->host, Port =>$url->port, Passive =>$is_passive,
140             ) or die "error fetching $url: $@";
141              
142 0 0         $ftp->login($url->user, $url->password)
143 0           or die "error on login $url: @{[ $ftp->message ]}";
144              
145 0           $ftp->binary;
146              
147 0           $ftp;
148             }
149              
150             1;
151              
152             __END__