| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
12
|
|
|
12
|
|
89286
|
use 5.008; # utf8 |
|
|
12
|
|
|
|
|
39
|
|
|
|
12
|
|
|
|
|
508
|
|
|
2
|
12
|
|
|
12
|
|
65
|
use strict; |
|
|
12
|
|
|
|
|
20
|
|
|
|
12
|
|
|
|
|
409
|
|
|
3
|
12
|
|
|
12
|
|
59
|
use warnings; |
|
|
12
|
|
|
|
|
20
|
|
|
|
12
|
|
|
|
|
371
|
|
|
4
|
12
|
|
|
12
|
|
12388
|
use utf8; |
|
|
12
|
|
|
|
|
110
|
|
|
|
12
|
|
|
|
|
86
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Path::IsDev; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '1.001002'; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# ABSTRACT: Determine if a given Path resembles a development source tree |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
12
|
|
|
12
|
|
13994
|
use Sub::Exporter -setup => { exports => [ is_dev => \&_build_is_dev, ], }; |
|
|
12
|
|
|
|
|
159796
|
|
|
|
12
|
|
|
|
|
158
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our $ENV_KEY_DEBUG = 'PATH_ISDEV_DEBUG'; |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $DEBUG = ( exists $ENV{$ENV_KEY_DEBUG} ? $ENV{$ENV_KEY_DEBUG} : undef ); |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub debug { |
|
42
|
0
|
0
|
|
0
|
1
|
0
|
return unless $DEBUG; |
|
43
|
0
|
|
|
|
|
0
|
return *STDERR->printf( qq{[Path::IsDev] %s\n}, shift ); |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub _build_is_dev { |
|
47
|
21
|
|
|
21
|
|
12128
|
my ( undef, undef, $arg ) = @_; |
|
48
|
|
|
|
|
|
|
|
|
49
|
21
|
|
|
|
|
33
|
my $isdev_object; |
|
50
|
|
|
|
|
|
|
return sub { |
|
51
|
10
|
|
|
10
|
|
5917
|
my ($path) = @_; |
|
52
|
10
|
|
66
|
|
|
66
|
$isdev_object ||= do { |
|
53
|
9
|
|
|
|
|
10087
|
require Path::IsDev::Object; |
|
54
|
9
|
50
|
|
|
|
35
|
Path::IsDev::Object->new( %{ $arg || {} } ); |
|
|
9
|
|
|
|
|
136
|
|
|
55
|
|
|
|
|
|
|
}; |
|
56
|
10
|
|
|
|
|
160
|
return $isdev_object->matches($path); |
|
57
|
21
|
|
|
|
|
115
|
}; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
*is_dev = _build_is_dev( 'Path::IsDev', 'is_dev', {} ); |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
1; |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
__END__ |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=pod |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=encoding UTF-8 |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=head1 NAME |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Path::IsDev - Determine if a given Path resembles a development source tree |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head1 VERSION |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
version 1.001002 |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
use Path::IsDev qw(is_dev); |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
if( is_dev('/some/path') ) { |
|
106
|
|
|
|
|
|
|
... |
|
107
|
|
|
|
|
|
|
} else { |
|
108
|
|
|
|
|
|
|
... |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
This module is more or less a bunch of heuristics for determining if a given path |
|
114
|
|
|
|
|
|
|
is a development tree root of some kind. |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
This has many useful applications, notably ones that require behaviours for "installed" |
|
117
|
|
|
|
|
|
|
modules to be different to those that are still "in development" |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=head2 debug |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Debug callback. |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
To enable debugging: |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
export PATH_ISDEV_DEBUG=1 |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head2 C<is_dev> |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Using an C<import>'ed C<is_dev>: |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
if( is_dev( $path ) ) { |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Though the actual heuristics used will be based on how C<import> was called. |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Additionally, you can call |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Path::IsDev::is_dev |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
without C<import>ing anything, and it will behave exactly the same as if you'd imported |
|
144
|
|
|
|
|
|
|
it using |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
use Path::IsDev qw( is_dev ); |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
That is, no C<set> specification is applicable, so you'll only get the "default". |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=begin MetaPOD::JSON v1.1.0 |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
{ |
|
153
|
|
|
|
|
|
|
"namespace":"Path::IsDev", |
|
154
|
|
|
|
|
|
|
"interface":"exporter" |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=end MetaPOD::JSON |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head1 UNDERSTANDING AND DEBUGGING THIS MODULE |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Understanding how this module works, is critical to understand where you can use it, and the consequences of using it. |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
This module operates on a very simplistic level, and its easy for false-positives to occur. |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
There are two types of Heuristics, Postive/Confirming Heuristics, and Negative/Disconfirming Heuristics. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Positive Heuristics and Negative Heuristics are based solely on the presence of specific marker files in a directory, or special |
|
169
|
|
|
|
|
|
|
marker directories. |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
For instance, the files C<META.yml>, C<Makefile.PL>, and C<Build.PL> are all B<Positive Heuristic> markers, because their |
|
172
|
|
|
|
|
|
|
presence often indicates a "root" of a development tree. |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
And for instance, the directories C<t/>, C<xt/> and C<.git/> are also B<Positive Heuristic> markers, because these structures |
|
175
|
|
|
|
|
|
|
are common in C<perl> development trees, and uncommon in install trees. |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
However, these markers sometimes go wrong, for instance, consider you have a C<local::lib> or C<perlbrew> install in C<$HOME> |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
$HOME/ |
|
180
|
|
|
|
|
|
|
$HOME/lib/ |
|
181
|
|
|
|
|
|
|
$HOME/perl5/perls/perl-5.19.3/lib/site_perl/ |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Etc. |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Under normal circumstances, neither C<$HOME> nor those 3 paths are considered C<dev>. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
However, all it takes to cause a false positive, is for somebody to install a C<t> or C<xt> directory, or a marker file in one of |
|
188
|
|
|
|
|
|
|
the above directories for C<path_isdev($dir)> to return true. |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
This may not be a problem, at least, until you use C<Path::FindDev> which combines C<Path::IsDev> with recursive up-level |
|
191
|
|
|
|
|
|
|
traversal. |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
$HOME/ |
|
194
|
|
|
|
|
|
|
$HOME/lib/ |
|
195
|
|
|
|
|
|
|
$HOME/perl5/perls/perl-5.19.3/lib/site_perl/ |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
find_dev('$HOME/perl5/perls/perl-5.19.3/lib/site_perl/') # returns false, because it is not inside a dev directory |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
mkdir $HOME/t |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
find_dev('$HOME/perl5/perls/perl-5.19.3/lib/site_perl/') # returns $HOME, because $HOME/t exists. |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
And it is this kind of problem that usually catches people off guard. |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
PATH_ISDEV_DEBUG=1 \ |
|
206
|
|
|
|
|
|
|
perl -Ilib -MPath::FindDev=find_dev \ |
|
207
|
|
|
|
|
|
|
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})" |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
... |
|
210
|
|
|
|
|
|
|
[Path::IsDev=0] + ::Tool::Dzil => 0 : dist.ini does not exist |
|
211
|
|
|
|
|
|
|
[Path::IsDev=0] + ::Tool::MakeMaker => 0 : Makefile.PL does not exist |
|
212
|
|
|
|
|
|
|
[Path::IsDev=0] + ::Tool::ModuleBuild => 0 : Build.PL does not exist |
|
213
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META => 0 : META.json does not exist |
|
214
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META => 1 : META.yml exists |
|
215
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META => 1 : /home/kent/perl5/META.yml is a file |
|
216
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META matched path /home/kent/perl5 |
|
217
|
|
|
|
|
|
|
/home/kent/perl5 |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Whoops!. |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META => 1 : META.yml exists |
|
222
|
|
|
|
|
|
|
[Path::IsDev=0] + ::META => 1 : /home/kent/perl5/META.yml is a file |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
No wonder! |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
rm /home/kent/perl5/META.yml |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
PATH_ISDEV_DEBUG=1 \ |
|
229
|
|
|
|
|
|
|
perl -Ilib -MPath::FindDev=find_dev \ |
|
230
|
|
|
|
|
|
|
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})" |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
... |
|
233
|
|
|
|
|
|
|
[Path::IsDev=0] Matching /home/kent/perl5 |
|
234
|
|
|
|
|
|
|
... |
|
235
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir => 0 : xt does not exist |
|
236
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir => 1 : t exists |
|
237
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir => 1 : /home/kent/perl5/t is a dir |
|
238
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir matched path /home/kent/perl5 |
|
239
|
|
|
|
|
|
|
/home/kent/perl5 |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Double whoops! |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir => 1 : t exists |
|
244
|
|
|
|
|
|
|
[Path::IsDev=0] + ::TestDir => 1 : /home/kent/perl5/t is a dir |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
And you could keep doing that until you rule out all the bad heuristics in your tree. |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
Or, you could use a negative heuristic. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
touch /home/kent/perl5/.path_isdev_ignore |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
PATH_ISDEV_DEBUG=1 \ |
|
253
|
|
|
|
|
|
|
perl -Ilib -MPath::FindDev=find_dev \ |
|
254
|
|
|
|
|
|
|
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})" |
|
255
|
|
|
|
|
|
|
... |
|
256
|
|
|
|
|
|
|
[Path::IsDev=0] Matching /home/kent/perl5 |
|
257
|
|
|
|
|
|
|
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : .path_isdev_ignore exists |
|
258
|
|
|
|
|
|
|
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : /home/kent/perl5/.path_isdev_ignore is a file |
|
259
|
|
|
|
|
|
|
[Path::IsDev=0] - ::IsDev::IgnoreFile excludes path /home/kent/perl5 |
|
260
|
|
|
|
|
|
|
[Path::IsDev=0] no match found |
|
261
|
|
|
|
|
|
|
... |
|
262
|
|
|
|
|
|
|
[Path::IsDev=0] Matching / |
|
263
|
|
|
|
|
|
|
... |
|
264
|
|
|
|
|
|
|
[Path::IsDev=0] no match found |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Success! |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : .path_isdev_ignore exists |
|
269
|
|
|
|
|
|
|
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : /home/kent/perl5/.path_isdev_ignore is a file |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=head1 HEURISTICS |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 Negative Heuristics bundled with this distribution |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
Just remember, a B<Negative> Heuristic B<excludes the path it is associated with> |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=over 4 |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=item * L<< C<IsDev::IgnoreFile>|Path::IsDev::NegativeHeuristic::IsDev::IgnoreFile >> - C<.path_isdev_ignore> |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=back |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head2 Positive Heuristics bundled with this distribution |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=over 4 |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=item * L<< C<Changelog>|Path::IsDev::Heuristic::Changelog >> - Files matching C<Changes>, C<Changelog>, and similar, case |
|
288
|
|
|
|
|
|
|
insensitive, extensions optional. |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=item * L<< C<DevDirMarker>|Path::IsDev::Heuristic::DevDirMarker >> - explicit C<.devdir> file to indicate a project root. |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=item * L<< C<META>|Path::IsDev::Heuristic::META >> - C<META.yml>/C<META.json> |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=item * L<< C<MYMETA>|Path::IsDev::Heuristic::MYMETA >> - C<MYMETA.yml>/C<MYMETA.json> |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item * L<< C<Makefile>|Path::IsDev::Heuristic::Makefile >> - Any C<Makefile> format documented supported by GNU Make |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=item * L<< C<TestDir>|Path::IsDev::Heuristic::TestDir >> - A directory called either C<t/> or C<xt/> |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=item * L<< C<Tool::DZil>|Path::IsDev::Heuristic::Tool::DZil >> - A C<dist.ini> file |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item * L<< C<Tool::MakeMaker>|Path::IsDev::Heuristic::Tool::MakeMaker >> - A C<Makefile.PL> file |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=item * L<< C<Tool::ModuleBuild>|Path::IsDev::Heuristic::Tool::ModuleBuild >> - A C<Build.PL> file |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=item * L<< C<VCS::Git>|Path::IsDev::Heuristic::VCS::Git >> - A C<.git> directory |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=back |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head1 HEURISTIC SETS |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head2 Heuristic Sets Bundled with this distribution |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=over 4 |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=item * L<< C<Basic>|Path::IsDev::HeuristicSet::Basic >> - The basic heuristic set that contains most, if not all heuristics. |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=back |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 ADVANCED USAGE |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head2 Custom Sets |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
C<Path::IsDev> has a system of "sets" of Heuristics, in order to allow for pluggable |
|
325
|
|
|
|
|
|
|
and flexible heuristic types. |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Though, for the vast majority of cases, this is not required. |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
use Path::IsDev is_dev => { set => 'Basic' }; |
|
330
|
|
|
|
|
|
|
use Path::IsDev is_dev => { set => 'SomeOtherSet' , -as => 'is_dev_other' }; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head2 Overriding the default set |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
If for whatever reason the C<Basic> set is insufficient, or if it false positives on your system for some reason, |
|
335
|
|
|
|
|
|
|
the "default" set can be overridden. |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
export PATH_ISDEV_DEFAULT_SET="SomeOtherSet" |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
... |
|
340
|
|
|
|
|
|
|
use Path::IsDev qw( is_dev ); |
|
341
|
|
|
|
|
|
|
is_dev('/some/path') # uses SomeOtherSet |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
Though this will only take priority in the event the set is not specified during C<import> |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
If this poses a security concern for the user, then this security hole can be eliminated by declaring the set you want in code: |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
export PATH_ISDEV_DEFAULT_SET="SomeOtherSet" |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
... |
|
350
|
|
|
|
|
|
|
use Path::IsDev is_dev => { set => 'Basic' }; |
|
351
|
|
|
|
|
|
|
is_dev('/some/path') # uses Basic, regardless of ENV |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head1 SECURITY |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
Its conceivable, than an evil user could construct an evil set, containing arbitrary and vulnerable code, and possibly stash that |
|
356
|
|
|
|
|
|
|
evil set in a poorly secured privileged users @INC |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
And if they managed to achieve that, if they could poison the privileged users %ENV, they could trick the privileged user into |
|
359
|
|
|
|
|
|
|
executing arbitrary code. |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Though granted, if you can do either of those 2 things, you're probably security vulnerable anyway, and granted, if you could do |
|
362
|
|
|
|
|
|
|
either of those 2 things you could do much more evil things by the following: |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
export PERL5OPT="-MEvil::Module" |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
So with that in understanding, saying this modules default utility is "insecure" is mostly a bogus argument. |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
And to that effect, this module does nothing to "lock down" that mechanism, and this module encourages you |
|
369
|
|
|
|
|
|
|
to B<NOT> force a set, unless you B<NEED> to, and strongly suggests that forcing a set for the purpose of security will achieve |
|
370
|
|
|
|
|
|
|
no real improvement in security, while simultaneously reducing utility. |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=head1 AUTHOR |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
Kent Fredric <kentfredric@gmail.com> |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
This software is copyright (c) 2014 by Kent Fredric <kentfredric@gmail.com>. |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
381
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut |