line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Astro::App::Satpass2::Utils; |
2
|
|
|
|
|
|
|
|
3
|
22
|
|
|
22
|
|
150524
|
use 5.008; |
|
22
|
|
|
|
|
99
|
|
4
|
|
|
|
|
|
|
|
5
|
22
|
|
|
22
|
|
113
|
use strict; |
|
22
|
|
|
|
|
43
|
|
|
22
|
|
|
|
|
456
|
|
6
|
22
|
|
|
22
|
|
103
|
use warnings; |
|
22
|
|
|
|
|
60
|
|
|
22
|
|
|
|
|
1048
|
|
7
|
|
|
|
|
|
|
|
8
|
22
|
|
|
22
|
|
10307
|
use parent qw{ Exporter }; |
|
22
|
|
|
|
|
6929
|
|
|
22
|
|
|
|
|
136
|
|
9
|
|
|
|
|
|
|
|
10
|
22
|
|
|
22
|
|
1335
|
use Cwd (); |
|
22
|
|
|
|
|
58
|
|
|
22
|
|
|
|
|
340
|
|
11
|
22
|
|
|
22
|
|
11735
|
use File::HomeDir; |
|
22
|
|
|
|
|
123412
|
|
|
22
|
|
|
|
|
1270
|
|
12
|
22
|
|
|
22
|
|
170
|
use File::Spec; |
|
22
|
|
|
|
|
51
|
|
|
22
|
|
|
|
|
559
|
|
13
|
22
|
|
|
22
|
|
4907
|
use Getopt::Long 2.33; |
|
22
|
|
|
|
|
82086
|
|
|
22
|
|
|
|
|
470
|
|
14
|
22
|
|
|
22
|
|
4266
|
use Scalar::Util 1.26 qw{ blessed looks_like_number }; |
|
22
|
|
|
|
|
419
|
|
|
22
|
|
|
|
|
1227
|
|
15
|
22
|
|
|
22
|
|
10639
|
use Text::ParseWords (); |
|
22
|
|
|
|
|
30849
|
|
|
22
|
|
|
|
|
3055
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '0.051'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our @CARP_NOT = qw{ |
20
|
|
|
|
|
|
|
Astro::App::Satpass2 |
21
|
|
|
|
|
|
|
Astro::App::Satpass2::Copier |
22
|
|
|
|
|
|
|
Astro::App::Satpass2::Format |
23
|
|
|
|
|
|
|
Astro::App::Satpass2::Format::Dump |
24
|
|
|
|
|
|
|
Astro::App::Satpass2::Format::Template |
25
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime |
26
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::Cldr |
27
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::DateTime |
28
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::DateTime::Cldr |
29
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::DateTime::Strftime |
30
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::POSIX::Strftime |
31
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatTime::Strftime |
32
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatValue |
33
|
|
|
|
|
|
|
Astro::App::Satpass2::FormatValue::Formatter |
34
|
|
|
|
|
|
|
Astro::App::Satpass2::Geocode |
35
|
|
|
|
|
|
|
Astro::App::Satpass2::Geocode::OSM |
36
|
|
|
|
|
|
|
Astro::App::Satpass2::Locale |
37
|
|
|
|
|
|
|
Astro::App::Satpass2::Locale::C |
38
|
|
|
|
|
|
|
Astro::App::Satpass2::Macro |
39
|
|
|
|
|
|
|
Astro::App::Satpass2::Macro::Code |
40
|
|
|
|
|
|
|
Astro::App::Satpass2::Macro::Command |
41
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime |
42
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime::Code |
43
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime::Date::Manip |
44
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime::Date::Manip::v5 |
45
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime::Date::Manip::v6 |
46
|
|
|
|
|
|
|
Astro::App::Satpass2::ParseTime::ISO8601 |
47
|
|
|
|
|
|
|
Astro::App::Satpass2::Utils |
48
|
|
|
|
|
|
|
Astro::App::Satpass2::Warner |
49
|
|
|
|
|
|
|
Astro::App::Satpass2::Wrap::Array |
50
|
|
|
|
|
|
|
}; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
our @EXPORT_OK = qw{ |
53
|
|
|
|
|
|
|
__arguments |
54
|
|
|
|
|
|
|
back_end |
55
|
|
|
|
|
|
|
__back_end_class_name_of_record |
56
|
|
|
|
|
|
|
expand_tilde find_package_pod |
57
|
|
|
|
|
|
|
has_method instance load_package merge_hashes my_dist_config quoter |
58
|
|
|
|
|
|
|
__date_manip_backend |
59
|
|
|
|
|
|
|
__legal_options |
60
|
|
|
|
|
|
|
__parse_class_and_args |
61
|
|
|
|
|
|
|
ARRAY_REF CODE_REF HASH_REF REGEXP_REF SCALAR_REF |
62
|
|
|
|
|
|
|
HAVE_DATETIME |
63
|
|
|
|
|
|
|
@CARP_NOT |
64
|
|
|
|
|
|
|
}; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
67
|
|
|
|
|
|
|
ref => [ grep { m/ _REF \z /smx } @EXPORT_OK ], |
68
|
|
|
|
|
|
|
); |
69
|
|
|
|
|
|
|
|
70
|
22
|
|
|
22
|
|
197
|
use constant ARRAY_REF => ref []; |
|
22
|
|
|
|
|
56
|
|
|
22
|
|
|
|
|
1751
|
|
71
|
22
|
|
|
22
|
|
154
|
use constant CODE_REF => ref sub {}; |
|
22
|
|
|
|
|
57
|
|
|
22
|
|
|
|
|
1316
|
|
72
|
22
|
|
|
22
|
|
150
|
use constant HASH_REF => ref {}; |
|
22
|
|
|
|
|
46
|
|
|
22
|
|
|
|
|
1401
|
|
73
|
22
|
|
|
22
|
|
138
|
use constant REGEXP_REF => ref qr{}; |
|
22
|
|
|
|
|
59
|
|
|
22
|
|
|
|
|
1890
|
|
74
|
22
|
|
|
22
|
|
188
|
use constant SCALAR_REF => ref \1; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
2344
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
{ |
77
|
|
|
|
|
|
|
local $@ = undef; |
78
|
|
|
|
|
|
|
|
79
|
22
|
|
50
|
|
|
65
|
use constant HAVE_DATETIME => eval { |
80
|
|
|
|
|
|
|
require DateTime; |
81
|
|
|
|
|
|
|
require DateTime::TimeZone; |
82
|
|
|
|
|
|
|
1; |
83
|
22
|
|
|
22
|
|
242
|
} || 0; |
|
22
|
|
|
|
|
66
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Documented in POD |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
{ |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
my @default_config = qw{default pass_through}; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub __arguments { |
94
|
350
|
|
|
350
|
|
1242
|
my ( $self, @args ) = @_; |
95
|
|
|
|
|
|
|
|
96
|
350
|
100
|
|
|
|
1034
|
has_method( $self, '__parse_time_reset' ) |
97
|
|
|
|
|
|
|
and $self->__parse_time_reset(); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
@args = map { |
100
|
350
|
100
|
|
|
|
840
|
has_method( $_, 'dereference' ) ? $_->dereference() : $_ |
|
1181
|
|
|
|
|
2070
|
|
101
|
|
|
|
|
|
|
} @args; |
102
|
|
|
|
|
|
|
|
103
|
350
|
|
|
|
|
665
|
my $code = \&{ ( caller 1 )[3] }; |
|
350
|
|
|
|
|
3932
|
|
104
|
|
|
|
|
|
|
|
105
|
350
|
100
|
|
|
|
1376
|
if ( HASH_REF eq ref $args[0] ) { |
106
|
6
|
|
|
|
|
15
|
my $opt = shift @args; |
107
|
6
|
|
|
|
|
16
|
my @orig_keys = sort keys %{ $opt }; |
|
6
|
|
|
|
|
37
|
|
108
|
6
|
|
|
|
|
28
|
my $lgl = $self->__legal_options( $code, $opt ); |
109
|
6
|
|
|
|
|
30
|
my %opt_name = ( |
110
|
|
|
|
|
|
|
level1 => 1, |
111
|
|
|
|
|
|
|
); |
112
|
6
|
|
|
|
|
17
|
my $name; |
113
|
6
|
|
|
|
|
26
|
foreach my $inx ( 0 .. $#$lgl ) { |
114
|
38
|
100
|
|
|
|
130
|
if ( CODE_REF eq ref $lgl->[$inx] ) { |
115
|
4
|
50
|
|
|
|
32
|
defined $name |
116
|
|
|
|
|
|
|
or die "Bug - \$name undefined. Inx $inx; lgl @$lgl"; |
117
|
4
|
100
|
|
|
|
18
|
if ( exists $opt->{$name} ) { |
118
|
2
|
|
|
|
|
16
|
$lgl->[$inx]->( $name, $opt->{$name} ); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} else { |
121
|
34
|
|
|
|
|
111
|
( $name = $lgl->[ $inx ] ) =~ s/ \W .* //smx; |
122
|
34
|
|
|
|
|
111
|
$opt_name{$name} = 1; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
} |
125
|
6
|
|
|
|
|
17
|
foreach my $key ( @orig_keys ) { |
126
|
9
|
50
|
|
|
|
26
|
$opt_name{$key} |
127
|
|
|
|
|
|
|
or __error_out( $self, wail => "Illegal option '$key'" ); |
128
|
|
|
|
|
|
|
} |
129
|
6
|
|
|
|
|
32
|
_apply_default( $self, $opt, \@args ); |
130
|
6
|
|
|
|
|
45
|
return( $self, $opt, @args ); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=begin comment |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
my @data = caller(1); |
136
|
|
|
|
|
|
|
my $code = \&{$data[3]}; |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my ( $err, %opt ); |
139
|
|
|
|
|
|
|
my $lgl = $self->__get_attr($code, 'Verb') || []; |
140
|
|
|
|
|
|
|
if ( @{ $lgl } && ':compute' eq $lgl->[0] ) { |
141
|
|
|
|
|
|
|
my $method = $lgl->[1]; |
142
|
|
|
|
|
|
|
unless ( defined $method ) { |
143
|
|
|
|
|
|
|
( $method = $data[3] ) =~ s/ .* :: //smx; |
144
|
|
|
|
|
|
|
$method = "__${method}_options"; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
$lgl = $self->$method( \%opt, $lgl ); |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=end comment |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
344
|
|
|
|
|
739
|
my ( $err, %opt ); |
155
|
344
|
|
|
|
|
1059
|
my $lgl = $self->__legal_options( $code, \%opt ); |
156
|
|
|
|
|
|
|
|
157
|
344
|
|
|
0
|
|
2551
|
local $SIG{__WARN__} = sub {$err = $_[0]}; |
|
0
|
|
|
|
|
0
|
|
158
|
344
|
|
50
|
|
|
1215
|
my $config = |
159
|
|
|
|
|
|
|
$self->__get_attr($code, 'Configure') || \@default_config; |
160
|
344
|
|
|
|
|
2176
|
my $go = Getopt::Long::Parser->new(config => $config); |
161
|
344
|
50
|
|
|
|
32883
|
if ( ! $go->getoptionsfromarray( |
162
|
|
|
|
|
|
|
\@args, \%opt, 'default=s', @$lgl) ) { |
163
|
0
|
|
|
|
|
0
|
__error_out( $self, wail => $err ); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
344
|
|
|
|
|
124244
|
_apply_default( $self, \%opt, \@args ); |
167
|
|
|
|
|
|
|
|
168
|
344
|
|
|
|
|
4113
|
return ( $self, \%opt, @args ); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub __legal_options { |
173
|
350
|
|
|
350
|
|
877
|
my ( $self, $code, $opt ) = @_; |
174
|
350
|
|
50
|
|
|
827
|
$code ||= \&{ ( caller 1 )[3] }; |
|
0
|
|
|
|
|
0
|
|
175
|
350
|
50
|
|
|
|
937
|
CODE_REF eq ref $code |
176
|
|
|
|
|
|
|
or __error_out( $self, weep => "$code not a CODE ref" ); |
177
|
350
|
|
50
|
|
|
750
|
$opt ||= {}; |
178
|
350
|
|
|
|
|
1110
|
my $lgl = $self->__get_attr( $code, Verb => [] ); |
179
|
350
|
100
|
100
|
|
|
737
|
if ( @{ $lgl } && ':compute' eq $lgl->[0] ) { |
|
350
|
|
|
|
|
1796
|
|
180
|
24
|
50
|
|
|
|
165
|
my $method = $lgl->[1] |
181
|
|
|
|
|
|
|
or __error_out( $self, weep => ':compute did not specify method' ); |
182
|
24
|
|
|
|
|
180
|
$lgl = $self->$method( $opt, $lgl ); |
183
|
|
|
|
|
|
|
} |
184
|
350
|
|
|
|
|
757
|
return $lgl; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub _apply_default { |
188
|
350
|
|
|
350
|
|
864
|
my ( $self, $opt, $args ) = @_; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
my $dflt = delete $opt->{default} |
191
|
350
|
100
|
|
|
|
1295
|
or return; |
192
|
|
|
|
|
|
|
|
193
|
2
|
50
|
|
|
|
18
|
if ( ARRAY_REF eq ref $dflt ) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Do nothing -- we already have what we want |
195
|
|
|
|
|
|
|
} elsif ( ref $dflt ) { |
196
|
0
|
|
|
|
|
0
|
__error_out( $self, |
197
|
|
|
|
|
|
|
wail => "Invalid default specification $dflt" ); |
198
|
|
|
|
|
|
|
} elsif ( my $code = $self->can( '__tokenize' ) ) { |
199
|
2
|
|
|
|
|
7
|
( $dflt ) = $code->( $self, $dflt ); |
200
|
|
|
|
|
|
|
} else { |
201
|
0
|
|
|
|
|
0
|
$dflt = [ Text::ParseWords::shellwords( $dflt ) ]; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
2
|
|
|
|
|
14
|
foreach my $inx ( 0 .. $#$dflt ) { |
205
|
14
|
100
|
66
|
|
|
60
|
defined $args->[$inx] |
206
|
|
|
|
|
|
|
and '' ne $args->[$inx] |
207
|
|
|
|
|
|
|
or $args->[$inx] = $dflt->[$inx]; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
2
|
|
|
|
|
8
|
return; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub back_end { |
214
|
0
|
|
|
0
|
1
|
0
|
my ( $self, @arg ) = @_; |
215
|
0
|
0
|
|
|
|
0
|
if ( @arg ) { |
216
|
0
|
|
|
|
|
0
|
my ( $pkg, @cls_arg ) = ( $self->__parse_class_and_args( |
217
|
|
|
|
|
|
|
$self->__back_end_default( $arg[0] ) ), @arg[ 1 .. $#arg ] ); |
218
|
0
|
|
|
|
|
0
|
my $cls = $self->load_package( { fatal => 1 }, $pkg, |
219
|
|
|
|
|
|
|
'DateTime::Calendar' ); |
220
|
0
|
|
|
|
|
0
|
$self->__back_end_validate( $cls, @cls_arg ); |
221
|
|
|
|
|
|
|
$self->{_back_end} = { |
222
|
0
|
|
|
|
|
0
|
arg => \@cls_arg, |
223
|
|
|
|
|
|
|
class => $cls, |
224
|
|
|
|
|
|
|
pkg => $pkg, |
225
|
|
|
|
|
|
|
}; |
226
|
0
|
|
|
|
|
0
|
$self->{back_end} = shift @arg; |
227
|
0
|
|
|
|
|
0
|
while ( @arg ) { |
228
|
0
|
|
|
|
|
0
|
my ( $name, $value ) = splice @arg, 0, 2; |
229
|
0
|
|
|
|
|
0
|
$self->{back_end} .= ",$name=$value"; |
230
|
|
|
|
|
|
|
} |
231
|
0
|
|
|
|
|
0
|
return $self; |
232
|
|
|
|
|
|
|
} else { |
233
|
|
|
|
|
|
|
wantarray |
234
|
|
|
|
|
|
|
and return ( $self->{_back_end}{pkg}, @{ |
235
|
0
|
0
|
|
|
|
0
|
$self->{_back_end}{arg} } ); |
|
0
|
|
|
|
|
0
|
|
236
|
0
|
|
|
|
|
0
|
return $self->{back_end}; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub __back_end_class_name_of_record { |
241
|
0
|
|
|
0
|
|
0
|
my ( $self, $name ) = @_; |
242
|
|
|
|
|
|
|
defined( my $back_end = $self->{_back_end}{class} ) |
243
|
0
|
0
|
|
|
|
0
|
or return $name; |
244
|
0
|
0
|
|
|
|
0
|
$back_end eq $self->__back_end_default() |
245
|
|
|
|
|
|
|
and return $name; |
246
|
0
|
|
|
|
|
0
|
$back_end =~ s/ \A DateTime::Calendar:: //smx; |
247
|
0
|
0
|
|
|
|
0
|
@{ $self->{_back_end}{arg} } |
|
0
|
|
|
|
|
0
|
|
248
|
|
|
|
|
|
|
or return "$name,back_end=$back_end"; |
249
|
0
|
|
|
|
|
0
|
my %dt_arg = @{ $self->{_back_end}{arg} }; |
|
0
|
|
|
|
|
0
|
|
250
|
0
|
|
|
|
|
0
|
foreach my $key ( sort keys %dt_arg ) { |
251
|
0
|
|
|
|
|
0
|
$back_end .= ",$key=$dt_arg{$key}"; |
252
|
|
|
|
|
|
|
} |
253
|
0
|
|
|
|
|
0
|
return "$name,back_end='$back_end'"; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# $backend = __date_manip_backend() |
257
|
|
|
|
|
|
|
# |
258
|
|
|
|
|
|
|
# This subroutine loads Date::Manip and returns the backend available, |
259
|
|
|
|
|
|
|
# either 5 or 6. If Date::Manip can not be loaded it returns undef. |
260
|
|
|
|
|
|
|
# |
261
|
|
|
|
|
|
|
# The idea here is to return 6 if the O-O interface is available, and 5 |
262
|
|
|
|
|
|
|
# if it is not but Date::Manip is. |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub __date_manip_backend { |
265
|
10
|
50
|
|
10
|
|
39
|
load_package( 'Date::Manip' ) |
266
|
|
|
|
|
|
|
or return; |
267
|
0
|
0
|
|
|
|
0
|
Date::Manip->isa( 'Date::Manip::DM6' ) |
268
|
|
|
|
|
|
|
and return 6; |
269
|
0
|
|
|
|
|
0
|
return 5; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
{ |
273
|
|
|
|
|
|
|
my %method_to_sub = ( |
274
|
|
|
|
|
|
|
whinge => 'carp', |
275
|
|
|
|
|
|
|
wail => 'croak', |
276
|
|
|
|
|
|
|
weep => 'confess', |
277
|
|
|
|
|
|
|
); |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# __error_out( $invocant, $method, @arg ) |
280
|
|
|
|
|
|
|
# |
281
|
|
|
|
|
|
|
# $method must be 'carp', 'croak', or 'confess'. |
282
|
|
|
|
|
|
|
# |
283
|
|
|
|
|
|
|
# If the $invocant is a blessed reference having method $method, |
284
|
|
|
|
|
|
|
# that method is called with @arg as arguments. |
285
|
|
|
|
|
|
|
# |
286
|
|
|
|
|
|
|
# Otherwise Carp is loaded, $method is mapped to the corresponding |
287
|
|
|
|
|
|
|
# Carp subroutine, and that subroutine is called with @arg as |
288
|
|
|
|
|
|
|
# arguments. |
289
|
|
|
|
|
|
|
# |
290
|
|
|
|
|
|
|
# If we have not thrown an exception as a result of all this, we |
291
|
|
|
|
|
|
|
# just return. |
292
|
|
|
|
|
|
|
sub __error_out { |
293
|
10
|
|
|
10
|
|
56
|
my ( $obj, $method, @arg ) = @_; |
294
|
10
|
50
|
|
|
|
58
|
$method_to_sub{$method} |
295
|
|
|
|
|
|
|
or $method = 'weep'; |
296
|
10
|
100
|
66
|
|
|
119
|
if ( blessed( $obj ) && $obj->can( $method ) |
297
|
|
|
|
|
|
|
) { |
298
|
5
|
|
|
|
|
39
|
$obj->$method( @arg ); |
299
|
|
|
|
|
|
|
} else { |
300
|
5
|
|
|
|
|
47
|
require Carp; |
301
|
5
|
50
|
|
|
|
94
|
if ( my $code = Carp->can( $method_to_sub{ $method } ) ) { |
302
|
5
|
|
|
|
|
8603
|
$code->( @arg ); |
303
|
|
|
|
|
|
|
} else { |
304
|
0
|
|
|
|
|
0
|
Carp::confess( @arg ); |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
} |
307
|
0
|
|
|
|
|
0
|
return; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub expand_tilde { |
312
|
37
|
|
|
37
|
1
|
170
|
my @args = @_; |
313
|
37
|
100
|
|
|
|
175
|
my ( $self, $fn ) = @args > 1 ? @args : ( undef, @args ); |
314
|
37
|
50
|
|
|
|
304
|
defined $fn |
315
|
20
|
|
|
|
|
131
|
and $fn =~ s{ \A ~ ( [^/]* ) }{ _user_home_dir( $self, $1 ) }smxe; |
316
|
28
|
|
|
|
|
407
|
return $fn; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
{ |
320
|
|
|
|
|
|
|
my %special = ( |
321
|
|
|
|
|
|
|
'+' => sub { return Cwd::cwd() }, |
322
|
|
|
|
|
|
|
'~' => sub { |
323
|
|
|
|
|
|
|
return my_dist_config(); |
324
|
|
|
|
|
|
|
}, |
325
|
|
|
|
|
|
|
'' => sub { return File::HomeDir->my_home() }, |
326
|
|
|
|
|
|
|
); |
327
|
|
|
|
|
|
|
# $dir = $self->_user_home_dir( $user ); |
328
|
|
|
|
|
|
|
# |
329
|
|
|
|
|
|
|
# Find the home directory for the given user, croaking if this can |
330
|
|
|
|
|
|
|
# not be done. If $user is '' or undef, returns the home directory |
331
|
|
|
|
|
|
|
# for the current user. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub _user_home_dir { |
334
|
20
|
|
|
20
|
|
115
|
my ( $self, $user ) = @_; |
335
|
20
|
50
|
|
|
|
85
|
defined $user |
336
|
|
|
|
|
|
|
or $user = ''; |
337
|
|
|
|
|
|
|
|
338
|
20
|
100
|
|
|
|
118
|
if ( my $code = $special{$user} ) { |
339
|
16
|
100
|
|
|
|
83
|
defined( my $special_dir = $code->( $user ) ) |
340
|
|
|
|
|
|
|
or _wail( $self, "Unable to find ~$user" ); |
341
|
9
|
|
|
|
|
155
|
return $special_dir; |
342
|
|
|
|
|
|
|
} else { |
343
|
4
|
100
|
|
|
|
57
|
defined( my $home_dir = File::HomeDir->users_home( $user ) ) |
344
|
|
|
|
|
|
|
or _wail( $self, "Unable to find home for $user" ); |
345
|
2
|
|
|
|
|
23
|
return $home_dir; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub find_package_pod { |
351
|
0
|
|
|
0
|
1
|
0
|
my ( $pkg ) = @_; |
352
|
0
|
|
|
|
|
0
|
( my $fn = $pkg ) =~ s{ :: }{/}smxg; |
353
|
0
|
|
|
|
|
0
|
foreach my $dir ( @INC ) { |
354
|
0
|
0
|
0
|
|
|
0
|
defined $dir |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
355
|
|
|
|
|
|
|
and not ref $dir |
356
|
|
|
|
|
|
|
and -d $dir |
357
|
|
|
|
|
|
|
and -x _ |
358
|
|
|
|
|
|
|
or next; |
359
|
0
|
|
|
|
|
0
|
foreach my $sfx ( qw{ pod pm } ) { |
360
|
0
|
|
|
|
|
0
|
my $path = "$dir/$fn.$sfx"; |
361
|
0
|
0
|
|
|
|
0
|
-r $path |
362
|
|
|
|
|
|
|
or next; |
363
|
0
|
|
|
|
|
0
|
return Cwd::abs_path( $path ); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
0
|
|
|
|
|
0
|
return; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub _wail { |
370
|
9
|
|
|
9
|
|
543
|
my ( $invocant, @msg ) = @_; |
371
|
9
|
|
|
|
|
286
|
__error_out( $invocant, wail => @msg ); |
372
|
0
|
|
|
|
|
0
|
return; # We should never get here, but Perl::Critic does not |
373
|
|
|
|
|
|
|
# know this. |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub has_method { |
377
|
2709
|
|
|
2709
|
1
|
5352
|
my ( $object, $method ) = @_; |
378
|
|
|
|
|
|
|
|
379
|
2709
|
100
|
|
|
|
8045
|
ref $object or return; |
380
|
995
|
100
|
|
|
|
3948
|
blessed( $object ) or return; |
381
|
970
|
|
|
|
|
5315
|
return $object->can( $method ); |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub instance { |
385
|
1501
|
|
|
1501
|
1
|
3302
|
my ( $object, $class ) = @_; |
386
|
1501
|
100
|
|
|
|
3610
|
ref $object or return; |
387
|
1475
|
100
|
|
|
|
6434
|
blessed( $object ) or return; |
388
|
981
|
|
|
|
|
5448
|
return $object->isa( $class ); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
sub _get_my_lib { |
392
|
127
|
|
|
127
|
|
402
|
my $my_lib = my_dist_config(); |
393
|
127
|
50
|
|
|
|
17361
|
if ( defined $my_lib ) { |
394
|
0
|
|
|
|
|
0
|
$my_lib = File::Spec->catdir( $my_lib, 'lib' ); |
395
|
0
|
0
|
|
|
|
0
|
-d $my_lib |
396
|
|
|
|
|
|
|
or $my_lib = undef; |
397
|
|
|
|
|
|
|
} |
398
|
127
|
|
|
|
|
328
|
return $my_lib; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
{ |
402
|
|
|
|
|
|
|
my %loaded; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# CAVEAT: |
405
|
|
|
|
|
|
|
# |
406
|
|
|
|
|
|
|
# Unfortunately as things currently stand, the version needs to be |
407
|
|
|
|
|
|
|
# maintained three places: |
408
|
|
|
|
|
|
|
# - lib/Astro/App/Satpass2/Utils.pm |
409
|
|
|
|
|
|
|
# - inc/My/Module/Recommend.pm |
410
|
|
|
|
|
|
|
# - inc/My/Module/Test/App.pm |
411
|
|
|
|
|
|
|
# These all need to stay the same. Sigh. |
412
|
|
|
|
|
|
|
# Any such should be in xt/author/consistent_module_versions.t |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
my %version = ( |
415
|
|
|
|
|
|
|
'DateTime::Calendar::Christian' => 0.06, |
416
|
|
|
|
|
|
|
); |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# Expose the module version so we can test for consistent definition. |
419
|
|
|
|
|
|
|
# IM(NS)HO the following annotation silences a false positive. |
420
|
|
|
|
|
|
|
sub __module_version { ## no critic (RequireArgUnpacking) |
421
|
0
|
|
|
0
|
|
0
|
my $module = $_[-1]; |
422
|
0
|
|
|
|
|
0
|
require Carp; |
423
|
0
|
0
|
|
|
|
0
|
exists $version{$module} |
424
|
|
|
|
|
|
|
or Carp::confess( "Bug - Module $module has no defined version" ); |
425
|
0
|
|
|
|
|
0
|
return $version{$module}; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
# my %valid_complaint = map { $_ => 1 } qw{ whinge wail weep }; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub load_package { |
431
|
|
|
|
|
|
|
# my ( $module, @prefix ) = @_; |
432
|
148
|
|
|
148
|
1
|
582
|
my @prefix = @_; |
433
|
148
|
|
|
|
|
286
|
my $self; |
434
|
148
|
100
|
|
|
|
770
|
blessed( $prefix[0] ) |
435
|
|
|
|
|
|
|
and $self = shift @prefix; |
436
|
148
|
100
|
|
|
|
670
|
my $opt = HASH_REF eq ref $prefix[0] ? shift @prefix : {}; |
437
|
148
|
|
|
|
|
330
|
my $module = shift @prefix; |
438
|
|
|
|
|
|
|
|
439
|
148
|
|
|
|
|
988
|
local @INC = @INC; |
440
|
|
|
|
|
|
|
|
441
|
148
|
100
|
|
|
|
642
|
my $use_lib = exists $opt->{lib} ? $opt->{lib} : _get_my_lib(); |
442
|
148
|
100
|
|
|
|
563
|
if ( defined $use_lib ) { |
443
|
1
|
|
|
|
|
7
|
require lib; |
444
|
1
|
|
|
|
|
15
|
lib->import( $use_lib ); |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
148
|
|
|
|
|
672
|
foreach ( $module, @prefix ) { |
448
|
212
|
50
|
|
|
|
578
|
'' eq $_ |
449
|
|
|
|
|
|
|
and next; |
450
|
212
|
50
|
|
|
|
1564
|
m/ \A [[:alpha:]]\w* (?: :: [[:alpha:]]\w* )* \z /smx |
451
|
|
|
|
|
|
|
and next; |
452
|
|
|
|
|
|
|
|
453
|
0
|
|
0
|
|
|
0
|
__error_out( $self, $opt->{complaint} || 'weep', |
454
|
|
|
|
|
|
|
"Invalid package name '$_'", |
455
|
|
|
|
|
|
|
); |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
148
|
|
|
|
|
624
|
my $key = join ' ', $module, @prefix; |
459
|
|
|
|
|
|
|
exists $loaded{$key} |
460
|
148
|
100
|
|
|
|
1170
|
and return $loaded{$key}; |
461
|
|
|
|
|
|
|
|
462
|
125
|
|
|
|
|
332
|
local $@ = undef; |
463
|
|
|
|
|
|
|
|
464
|
125
|
|
|
|
|
314
|
push @prefix, ''; |
465
|
125
|
|
|
|
|
316
|
foreach my $pfx ( @prefix ) { |
466
|
171
|
|
|
|
|
501
|
my $package = join '::', grep { $_ ne '' } $pfx, $module; |
|
342
|
|
|
|
|
1224
|
|
467
|
171
|
50
|
|
|
|
558
|
'' eq $package |
468
|
|
|
|
|
|
|
and next; |
469
|
171
|
|
|
|
|
902
|
( my $fn = $package ) =~ s{ :: }{/}smxg; |
470
|
171
|
100
|
|
|
|
406
|
eval { |
471
|
171
|
|
|
|
|
33399
|
require "$fn.pm"; ## no critic (RequireBarewordIncludes) |
472
|
71
|
|
|
|
|
5465
|
1; |
473
|
|
|
|
|
|
|
} or next; |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
not $version{$package} |
476
|
71
|
50
|
|
|
|
261
|
or $package->VERSION( $version{$package} ); |
477
|
|
|
|
|
|
|
|
478
|
71
|
|
|
|
|
711
|
return ( $loaded{$key} = $package ); |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
54
|
100
|
|
|
|
352
|
if ( $opt->{fatal} ) { |
482
|
1
|
|
|
|
|
14
|
__error_out( $self, $opt->{fatal}, "Can not load $module: $@" ); |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
53
|
|
|
|
|
245
|
$loaded{$key} = undef; |
486
|
|
|
|
|
|
|
|
487
|
53
|
|
|
|
|
470
|
return; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
# The Perl::Critic annotation on the following line should not (strictly |
492
|
|
|
|
|
|
|
# speaking) be necessary - but Subroutines::RequireArgUnpacking does not |
493
|
|
|
|
|
|
|
# understand the unpacking to be subject to the configuration |
494
|
|
|
|
|
|
|
# allow_arg_unpacking = grep |
495
|
|
|
|
|
|
|
sub merge_hashes { ## no critic (RequireArgUnpacking) |
496
|
0
|
|
|
0
|
1
|
0
|
my @args = grep { HASH_REF eq ref $_ } @_; |
|
0
|
|
|
|
|
0
|
|
497
|
0
|
0
|
|
|
|
0
|
@args == 1 |
498
|
|
|
|
|
|
|
and return $args[0]; |
499
|
0
|
|
|
|
|
0
|
my %rslt; |
500
|
0
|
|
|
|
|
0
|
foreach my $hash ( @args ) { |
501
|
0
|
|
|
|
|
0
|
@rslt{ keys %{ $hash } } = values %{ $hash }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
502
|
|
|
|
|
|
|
} |
503
|
0
|
|
|
|
|
0
|
return \%rslt; |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
|
506
|
22
|
|
|
22
|
|
201
|
use constant MY_PACKAGE_NAME => 'Astro-App-Satpass2'; |
|
22
|
|
|
|
|
67
|
|
|
22
|
|
|
|
|
16420
|
|
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub my_dist_config { |
509
|
139
|
|
|
139
|
1
|
371
|
my ( $opt ) = @_; |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
defined $ENV{ASTRO_APP_SATPASS2_CONFIG_DIR} |
512
|
139
|
100
|
|
|
|
533
|
and return Cwd::abs_path( $ENV{ASTRO_APP_SATPASS2_CONFIG_DIR} ); |
513
|
|
|
|
|
|
|
|
514
|
136
|
|
50
|
|
|
1967
|
my $code = __PACKAGE__->can( "_my_dist_config_$^O" ) || \&_my_dist_config_; |
515
|
136
|
|
|
|
|
477
|
return $code->( $opt ); |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub _my_dist_config_ { |
519
|
136
|
|
|
136
|
|
356
|
my ( $opt ) = @_; |
520
|
|
|
|
|
|
|
return File::HomeDir->my_dist_config( |
521
|
|
|
|
|
|
|
MY_PACKAGE_NAME, |
522
|
136
|
|
|
|
|
1566
|
{ create => $opt->{'create-directory'} }, |
523
|
|
|
|
|
|
|
); |
524
|
|
|
|
|
|
|
} |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
# Called dynamically by my_dist_config() if $^O is 'darwin'. |
527
|
|
|
|
|
|
|
sub _my_dist_config_darwin { ## no critic (ProhibitUnusedPrivateSubroutines) |
528
|
|
|
|
|
|
|
# my ( $opt ) = @_; |
529
|
0
|
0
|
|
0
|
|
0
|
my $rslt = File::HomeDir->my_dist_data( MY_PACKAGE_NAME ) |
530
|
|
|
|
|
|
|
or goto &_my_dist_config_; |
531
|
0
|
|
|
|
|
0
|
return $rslt; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub __parse_class_and_args { |
535
|
43
|
|
|
43
|
|
1013
|
my ( $self, $arg, @rest ) = @_; |
536
|
43
|
|
|
|
|
302
|
my ( $cls, @val ) = |
537
|
|
|
|
|
|
|
Text::ParseWords::parse_line( qr{ , }smx, 0, $arg ); |
538
|
43
|
50
|
33
|
|
|
4862
|
unless ( defined $cls && |
539
|
|
|
|
|
|
|
$cls =~ m/ \A [_[:alpha:]] \w* (?: :: \w+ )* \z /smx ) { |
540
|
0
|
0
|
|
|
|
0
|
$cls = defined $cls ? "'$cls'" : 'undef'; |
541
|
0
|
0
|
|
|
|
0
|
my $warner = $self->can( 'wail' ) ? $self : $self->warner(); |
542
|
0
|
|
|
|
|
0
|
$warner->wail( "Invalid class name $cls" ); |
543
|
|
|
|
|
|
|
} |
544
|
43
|
|
|
|
|
153
|
foreach ( @val ) { |
545
|
4
|
50
|
|
|
|
14
|
m/ = /smx |
546
|
|
|
|
|
|
|
or $_ .= '='; |
547
|
|
|
|
|
|
|
}; |
548
|
43
|
|
|
|
|
190
|
return ( $cls, ( map { split qr{ = }smx, $_, 2 } @val ), @rest ); |
|
4
|
|
|
|
|
54
|
|
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub quoter { |
552
|
50
|
|
|
50
|
1
|
313
|
my @args = @_; |
553
|
50
|
|
|
|
|
109
|
my @rslt = map { _quoter( $_ ) } @args; |
|
100
|
|
|
|
|
264
|
|
554
|
50
|
100
|
|
|
|
407
|
return wantarray ? @rslt : join ' ', @rslt; |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
sub _quoter { |
558
|
100
|
|
|
100
|
|
205
|
my ( $string ) = @_; |
559
|
100
|
50
|
|
|
|
215
|
return 'undef' unless defined $string; |
560
|
100
|
100
|
|
|
|
350
|
return $string if looks_like_number ($string); |
561
|
84
|
50
|
|
|
|
218
|
return q{''} unless $string; |
562
|
84
|
100
|
|
|
|
355
|
return $string unless $string =~ m/ [\s'"\$] /smx; |
563
|
16
|
|
|
|
|
43
|
$string =~ s/ ( [\\'] ) /\\$1/smxg; |
564
|
16
|
|
|
|
|
60
|
return qq{'$string'}; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
1; |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
__END__ |