line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
329
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
2
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
53
|
|
3
|
|
|
|
|
|
|
package CPAN::Uploader; |
4
|
|
|
|
|
|
|
# ABSTRACT: upload things to the CPAN |
5
|
|
|
|
|
|
|
$CPAN::Uploader::VERSION = '0.103007'; |
6
|
|
|
|
|
|
|
=head1 ORIGIN |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
This code is mostly derived from C by Brad Fitzpatrick, which |
9
|
|
|
|
|
|
|
in turn was based on C by Neil Bowers. I (I) didn't want to |
10
|
|
|
|
|
|
|
have to use a C call to run either of those, so I refactored the code |
11
|
|
|
|
|
|
|
into this module. |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=cut |
14
|
|
|
|
|
|
|
|
15
|
1
|
|
|
1
|
|
6
|
use Carp (); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
23
|
|
16
|
1
|
|
|
1
|
|
8
|
use File::Basename (); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
11
|
|
17
|
1
|
|
|
1
|
|
473
|
use File::HomeDir (); |
|
1
|
|
|
|
|
4427
|
|
|
1
|
|
|
|
|
26
|
|
18
|
1
|
|
|
1
|
|
5
|
use File::Spec; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
14
|
|
19
|
1
|
|
|
1
|
|
416
|
use HTTP::Tiny::UA; |
|
1
|
|
|
|
|
49287
|
|
|
1
|
|
|
|
|
25
|
|
20
|
1
|
|
|
1
|
|
436
|
use HTTP::Tiny::Multipart; |
|
1
|
|
|
|
|
2068
|
|
|
1
|
|
|
|
|
24
|
|
21
|
1
|
|
|
1
|
|
475
|
use URI; |
|
1
|
|
|
|
|
5345
|
|
|
1
|
|
|
|
|
42
|
|
22
|
|
|
|
|
|
|
|
23
|
1
|
|
|
1
|
|
9
|
use constant ALT => 'tinyua'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
931
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $UPLOAD_URI = $ENV{CPAN_UPLOADER_UPLOAD_URI} |
26
|
|
|
|
|
|
|
|| 'https://pause.perl.org/pause/authenquery'; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=method upload_file |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
CPAN::Uploader->upload_file($file, \%arg); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$uploader->upload_file($file); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Valid arguments are: |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
user - (required) your CPAN / PAUSE id |
37
|
|
|
|
|
|
|
password - (required) your CPAN / PAUSE password |
38
|
|
|
|
|
|
|
subdir - the directory (under your home directory) to upload to |
39
|
|
|
|
|
|
|
http_proxy - uri of the http proxy to use |
40
|
|
|
|
|
|
|
upload_uri - uri of the upload handler; usually the default (PAUSE) is right |
41
|
|
|
|
|
|
|
debug - if set to true, spew lots more debugging output |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
This method attempts to actually upload the named file to the CPAN. It will |
44
|
|
|
|
|
|
|
raise an exception on error. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=cut |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub upload_file { |
49
|
0
|
|
|
0
|
0
|
|
my ($self, $file, $arg) = @_; |
50
|
|
|
|
|
|
|
|
51
|
0
|
0
|
0
|
|
|
|
Carp::confess(q{don't supply %arg when calling upload_file on an object}) |
52
|
|
|
|
|
|
|
if $arg and ref $self; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# class call with no args is no good |
55
|
0
|
0
|
0
|
|
|
|
Carp::confess(q{need to supply %arg when calling upload_file from the class}) |
56
|
|
|
|
|
|
|
if not (ref $self) and not $arg; |
57
|
|
|
|
|
|
|
|
58
|
0
|
0
|
|
|
|
|
$self = $self->new($arg) if $arg; |
59
|
|
|
|
|
|
|
|
60
|
0
|
0
|
|
|
|
|
if ($arg->{dry_run}) { |
61
|
0
|
|
|
|
|
|
require Data::Dumper; |
62
|
0
|
|
|
|
|
|
$self->log("By request, cowardly refusing to do anything at all."); |
63
|
0
|
|
|
|
|
|
$self->log( |
64
|
|
|
|
|
|
|
"The following arguments would have been used to upload: \n" |
65
|
|
|
|
|
|
|
. '$self: ' . Data::Dumper::Dumper($self) |
66
|
|
|
|
|
|
|
. '$file: ' . Data::Dumper::Dumper($file) |
67
|
|
|
|
|
|
|
); |
68
|
|
|
|
|
|
|
} else { |
69
|
0
|
|
|
|
|
|
$self->_upload($file); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub _ua_string { |
74
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
75
|
0
|
|
0
|
|
|
|
my $class = ref $self || $self; |
76
|
0
|
0
|
|
|
|
|
my $version = defined $class->VERSION ? $class->VERSION : 'dev'; |
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
|
return "$class/$version"; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
0
|
0
|
|
0
|
0
|
|
sub target { shift->{target} || 'PAUSE' } |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub _upload { |
84
|
0
|
|
|
0
|
|
|
my $self = shift; |
85
|
0
|
|
|
|
|
|
my $file = shift; |
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
|
$self->log("registering upload with " . $self->target . " web server"); |
88
|
|
|
|
|
|
|
|
89
|
0
|
0
|
|
|
|
|
my $agent = HTTP::Tiny::UA->new( |
90
|
|
|
|
|
|
|
agent => $self->_ua_string, |
91
|
|
|
|
|
|
|
($self->{http_proxy} ? (http_proxy => $self->{http_proxy}) : ()), |
92
|
|
|
|
|
|
|
); |
93
|
|
|
|
|
|
|
|
94
|
0
|
|
0
|
|
|
|
my $uri = URI->new($self->{upload_uri} || $UPLOAD_URI); |
95
|
0
|
|
|
|
|
|
$uri->userinfo(join ':', $self->{user}, $self->{password}); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Make the request to the PAUSE web server |
98
|
0
|
|
|
|
|
|
$self->log("POSTing upload for $file to $uri"); |
99
|
0
|
|
|
|
|
|
my $response = $agent->post_multipart($uri, { |
100
|
|
|
|
|
|
|
HIDDENNAME => $self->{user}, |
101
|
|
|
|
|
|
|
CAN_MULTIPART => 1, |
102
|
|
|
|
|
|
|
pause99_add_uri_upload => File::Basename::basename($file), |
103
|
|
|
|
|
|
|
SUBMIT_pause99_add_uri_httpupload => " Upload this file from my disk ", |
104
|
|
|
|
|
|
|
pause99_add_uri_uri => "", |
105
|
|
|
|
|
|
|
pause99_add_uri_httpupload => { |
106
|
|
|
|
|
|
|
filename => $file, |
107
|
0
|
0
|
|
|
|
|
content => do {open my $fh, '<', $file; binmode $fh; local $/ = <$fh>}, |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
}, |
109
|
|
|
|
|
|
|
($self->{subdir} ? (pause99_add_uri_subdirtext => $self->{subdir}) : ()), |
110
|
|
|
|
|
|
|
}); |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# So, how'd we do? |
113
|
0
|
0
|
|
|
|
|
if (not defined $response) { |
114
|
0
|
|
|
|
|
|
die "Request completely failed - we got undef back: $!"; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
0
|
0
|
|
|
|
|
if (!$response->success) { |
118
|
0
|
0
|
|
|
|
|
if ($response->status eq '404') { |
119
|
0
|
|
|
|
|
|
die $self->target, "'s CGI for handling messages seems to have moved!\n", |
120
|
|
|
|
|
|
|
"(HTTP response code of 404 from the ", $self->target, " web server)\n", |
121
|
|
|
|
|
|
|
"It used to be: ", $uri, "\n", |
122
|
0
|
|
|
|
|
|
"Please inform the maintainer of @{[__PACKAGE__]}.\n"; |
123
|
|
|
|
|
|
|
} else { |
124
|
0
|
|
|
|
|
|
die "request failed with error code ", $response->status, |
125
|
|
|
|
|
|
|
"\n Message: ", $response->reason, "\n"; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} else { |
128
|
0
|
|
|
|
|
|
$self->log_debug($_) for ( |
129
|
|
|
|
|
|
|
"Looks OK!", |
130
|
|
|
|
|
|
|
"----- RESPONSE BEGIN -----\n" . |
131
|
|
|
|
|
|
|
$response->content . "\n" . |
132
|
|
|
|
|
|
|
"----- RESPONSE END -------\n" |
133
|
|
|
|
|
|
|
); |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
$self->log($self->target . " add message sent ok [" . $response->status . "]"); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=method new |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
my $uploader = CPAN::Uploader->new(\%arg); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
This method returns a new uploader. You probably don't need to worry about |
145
|
|
|
|
|
|
|
this method. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
Valid arguments are the same as those to C. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub new { |
152
|
0
|
|
|
0
|
0
|
|
my ($class, $arg) = @_; |
153
|
|
|
|
|
|
|
|
154
|
0
|
|
0
|
|
|
|
$arg->{$_} or Carp::croak("missing $_ argument") for qw(user password); |
155
|
0
|
|
|
|
|
|
bless $arg => $class; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=method read_config_file |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my $config = CPAN::Uploader->read_config_file( $filename ); |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
This reads the config file and returns a hashref of its contents that can be |
163
|
|
|
|
|
|
|
used as configuration for CPAN::Uploader. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
If no filename is given, it looks for F<.pause> in the user's home directory |
166
|
|
|
|
|
|
|
(from the env var C, or the current directory if C isn't set). |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
See L for the config format. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=cut |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub read_config_file { |
173
|
0
|
|
|
0
|
0
|
|
my ($class, $filename) = @_; |
174
|
|
|
|
|
|
|
|
175
|
0
|
0
|
|
|
|
|
unless (defined $filename) { |
176
|
0
|
|
0
|
|
|
|
my $home = File::HomeDir->my_home || '.'; |
177
|
0
|
|
|
|
|
|
$filename = File::Spec->catfile($home, '.pause'); |
178
|
|
|
|
|
|
|
|
179
|
0
|
0
|
0
|
|
|
|
return {} unless -e $filename and -r _; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
my %conf; |
183
|
0
|
0
|
|
|
|
|
if ( eval { require Config::Identity } ) { |
|
0
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
%conf = Config::Identity->load($filename); |
185
|
0
|
0
|
|
|
|
|
$conf{user} = delete $conf{username} unless $conf{user}; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
else { # Process .pause manually |
188
|
0
|
0
|
|
|
|
|
open my $pauserc, '<', $filename |
189
|
|
|
|
|
|
|
or die "can't open $filename for reading: $!"; |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
while (<$pauserc>) { |
192
|
0
|
|
|
|
|
|
chomp; |
193
|
0
|
0
|
0
|
|
|
|
next unless $_ and $_ !~ /^\s*#/; |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
my ($k, $v) = /^\s*(\w+)\s+(.+)$/; |
196
|
0
|
0
|
|
|
|
|
Carp::croak "multiple enties for $k" if $conf{$k}; |
197
|
0
|
|
|
|
|
|
$conf{$k} = $v; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
0
|
|
|
|
|
|
return \%conf; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=method log |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
$uploader->log($message); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
This method logs the given string. The default behavior is to print it to the |
209
|
|
|
|
|
|
|
screen. The message should not end in a newline, as one will be added as |
210
|
|
|
|
|
|
|
needed. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=cut |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub log { |
215
|
0
|
|
|
0
|
0
|
|
shift; |
216
|
0
|
|
|
|
|
|
print "$_[0]\n" |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=method log_debug |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
This method behaves like C>, but only logs the message if the |
222
|
|
|
|
|
|
|
CPAN::Uploader is in debug mode. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub log_debug { |
227
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
228
|
0
|
0
|
|
|
|
|
return unless $self->{debug}; |
229
|
0
|
|
|
|
|
|
$self->log($_[0]); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
1; |