File Coverage

lib/ExtUtils/Command.pm
Criterion Covered Total %
statement 89 105 84.7
branch 25 40 62.5
condition 7 15 46.6
subroutine 19 19 100.0
pod 12 13 92.3
total 152 192 79.1


line stmt bran cond sub pod time code
1              
2             use 5.00503;
3 3     3   18554 use strict;
  3         23  
4 3     3   14 use warnings;
  3         3  
  3         49  
5 3     3   11 require Exporter;
  3         5  
  3         100  
6             use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
7 3     3   14 @ISA = qw(Exporter);
  3         4  
  3         5668  
8             @EXPORT = qw(cp rm_f rm_rf mv cat eqtime mkpath touch test_f test_d chmod
9             dos2unix);
10             $VERSION = '7.64';
11             $VERSION =~ tr/_//d;
12              
13             my $Is_VMS = $^O eq 'VMS';
14             my $Is_VMS_mode = $Is_VMS;
15             my $Is_VMS_noefs = $Is_VMS;
16             my $Is_Win32 = $^O eq 'MSWin32';
17              
18             if( $Is_VMS ) {
19             my $vms_unix_rpt;
20             my $vms_efs;
21             my $vms_case;
22              
23             if (eval { local $SIG{__DIE__};
24             local @INC = @INC;
25             pop @INC if $INC[-1] eq '.';
26             require VMS::Feature; }) {
27             $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
28             $vms_efs = VMS::Feature::current("efs_charset");
29             $vms_case = VMS::Feature::current("efs_case_preserve");
30             } else {
31             my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
32             my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
33             my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
34             $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
35             $vms_efs = $efs_charset =~ /^[ET1]/i;
36             $vms_case = $efs_case =~ /^[ET1]/i;
37             }
38             $Is_VMS_mode = 0 if $vms_unix_rpt;
39             $Is_VMS_noefs = 0 if ($vms_efs);
40             }
41              
42              
43             =head1 NAME
44              
45             ExtUtils::Command - utilities to replace common UNIX commands in Makefiles etc.
46              
47             =head1 SYNOPSIS
48              
49             perl -MExtUtils::Command -e cat files... > destination
50             perl -MExtUtils::Command -e mv source... destination
51             perl -MExtUtils::Command -e cp source... destination
52             perl -MExtUtils::Command -e touch files...
53             perl -MExtUtils::Command -e rm_f files...
54             perl -MExtUtils::Command -e rm_rf directories...
55             perl -MExtUtils::Command -e mkpath directories...
56             perl -MExtUtils::Command -e eqtime source destination
57             perl -MExtUtils::Command -e test_f file
58             perl -MExtUtils::Command -e test_d directory
59             perl -MExtUtils::Command -e chmod mode files...
60             ...
61              
62             =head1 DESCRIPTION
63              
64             The module is used to replace common UNIX commands. In all cases the
65             functions work from @ARGV rather than taking arguments. This makes
66             them easier to deal with in Makefiles. Call them like this:
67              
68             perl -MExtUtils::Command -e some_command some files to work on
69              
70             and I<NOT> like this:
71              
72             perl -MExtUtils::Command -e 'some_command qw(some files to work on)'
73              
74             For that use L<Shell::Command>.
75              
76             Filenames with * and ? will be glob expanded.
77              
78              
79             =head2 FUNCTIONS
80              
81             =over 4
82              
83             =cut
84              
85             # VMS uses % instead of ? to mean "one character"
86             my $wild_regex = $Is_VMS ? '*%' : '*?';
87             {
88             @ARGV = map(/[$wild_regex]/o ? glob($_) : $_,@ARGV);
89             }
90 25 100   25 0 1513  
91              
92             =item cat
93              
94             cat file ...
95              
96             Concatenates all files mentioned on command line to STDOUT.
97              
98             =cut
99              
100             {
101             expand_wildcards();
102             print while (<>);
103             }
104 1     1 1 94  
105 1         63 =item eqtime
106              
107             eqtime source destination
108              
109             Sets modified time of destination to that of source.
110              
111             =cut
112              
113             {
114             my ($src,$dst) = @ARGV;
115             local @ARGV = ($dst); touch(); # in case $dst doesn't exist
116             utime((stat($src))[8,9],$dst);
117             }
118 2     2 1 1060  
119 2         6 =item rm_rf
  2         5  
120 2         39  
121             rm_rf files or directories ...
122              
123             Removes files and directories - recursively (even if readonly)
124              
125             =cut
126              
127             {
128             expand_wildcards();
129             require File::Path;
130             File::Path::rmtree([grep -e $_,@ARGV],0,0);
131             }
132              
133 2     2 1 1214 =item rm_f
134 2         16  
135 2         832 rm_f file ...
136              
137             Removes files (even if readonly)
138              
139             =cut
140              
141             expand_wildcards();
142              
143             foreach my $file (@ARGV) {
144             next unless -f $file;
145              
146             next if _unlink($file);
147 1     1 1 589  
148             chmod(0777, $file);
149 1         3  
150 2 50       28 next if _unlink($file);
151              
152 2 50       6 require Carp;
153             Carp::carp("Cannot delete $file: $!");
154 0         0 }
155             }
156 0 0       0  
157             my $files_unlinked = 0;
158 0         0 foreach my $file (@_) {
159 0         0 my $delete_count = 0;
160             $delete_count++ while unlink $file;
161             $files_unlinked++ if $delete_count;
162             }
163             return $files_unlinked;
164 2     2   5 }
165 2         4  
166 2         3  
167 2         143 =item touch
168 2 50       10  
169             touch file ...
170 2         7  
171             Makes files exist, with current timestamp
172              
173             =cut
174              
175             my $t = time;
176             expand_wildcards();
177             foreach my $file (@ARGV) {
178             open(FILE,">>$file") || die "Cannot write $file:$!";
179             close(FILE);
180             utime($t,$t,$file);
181             }
182             }
183 4     4 1 2003028  
184 4         12 =item mv
185 4         11  
186 4 50       280 mv source_file destination_file
187 4         47 mv source_file source_file destination_dir
188 4         74  
189             Moves source to destination. Multiple sources are allowed if
190             destination is an existing directory.
191              
192             Returns true if all moves succeeded, false otherwise.
193              
194             =cut
195              
196             expand_wildcards();
197             my @src = @ARGV;
198             my $dst = pop @src;
199              
200             if (@src > 1 && ! -d $dst) {
201             require Carp;
202             Carp::croak("Too many arguments");
203             }
204              
205 2     2 1 516 require File::Copy;
206 2         6 my $nok = 0;
207 2         3 foreach my $src (@src) {
208             $nok ||= !File::Copy::move($src,$dst);
209 2 100 66     20 }
210 1         8 return !$nok;
211 1         120 }
212              
213             =item cp
214 1         6  
215 1         3 cp source_file destination_file
216 1         2 cp source_file source_file destination_dir
217 1   33     7  
218             Copies sources to the destination. Multiple sources are allowed if
219 1         192 destination is an existing directory.
220              
221             Returns true if all copies succeeded, false otherwise.
222              
223             =cut
224              
225             expand_wildcards();
226             my @src = @ARGV;
227             my $dst = pop @src;
228              
229             if (@src > 1 && ! -d $dst) {
230             require Carp;
231             Carp::croak("Too many arguments");
232             }
233              
234             require File::Copy;
235 3     3 1 2050 my $nok = 0;
236 3         10 foreach my $src (@src) {
237 3         6 $nok ||= !File::Copy::copy($src,$dst);
238              
239 3 100 66     32 # Win32 does not update the mod time of a copied file, just the
240 1         11 # created time which make does not look at.
241 1         168 utime(time, time, $dst) if $Is_Win32;
242             }
243             return $nok;
244 2         1020 }
245 2         4367  
246 2         9 =item chmod
247 2   33     11  
248             chmod mode files ...
249              
250             Sets UNIX like permissions 'mode' on all the files. e.g. 0666
251 2 50       802  
252             =cut
253 2         7  
254             local @ARGV = @ARGV;
255             my $mode = shift(@ARGV);
256             expand_wildcards();
257              
258             if( $Is_VMS_mode && $Is_VMS_noefs) {
259             require File::Spec;
260             foreach my $idx (0..$#ARGV) {
261             my $path = $ARGV[$idx];
262             next unless -d $path;
263              
264             # chmod 0777, [.foo.bar] doesn't work on VMS, you have to do
265 7     7 1 3383 # chmod 0777, [.foo]bar.dir
266 7         15 my @dirs = File::Spec->splitdir( $path );
267 7         17 $dirs[-1] .= '.dir';
268             $path = File::Spec->catfile(@dirs);
269 7 50 33     22  
270 0         0 $ARGV[$idx] = $path;
271 0         0 }
272 0         0 }
273 0 0       0  
274             chmod(oct $mode,@ARGV) || die "Cannot chmod ".join(' ',$mode,@ARGV).":$!";
275             }
276              
277 0         0 =item mkpath
278 0         0  
279 0         0 mkpath directory ...
280              
281 0         0 Creates directories, including any parent directories.
282              
283             =cut
284              
285 7 50       152 {
286             expand_wildcards();
287             require File::Path;
288             File::Path::mkpath([@ARGV],0,0777);
289             }
290              
291             =item test_f
292              
293             test_f file
294              
295             Tests if a file exists. I<Exits> with 0 if it does, 1 if it does not (ie.
296             shell's idea of true and false).
297              
298 3     3 1 1951 =cut
299 3         20  
300 3         629 {
301             exit(-f $ARGV[0] ? 0 : 1);
302             }
303              
304             =item test_d
305              
306             test_d directory
307              
308             Tests if a directory exists. I<Exits> with 0 if it does, 1 if it does
309             not (ie. shell's idea of true and false).
310              
311             =cut
312              
313             {
314 2 100   2 1 3274 exit(-d $ARGV[0] ? 0 : 1);
315             }
316              
317             =item dos2unix
318              
319             dos2unix files or dirs ...
320              
321             Converts DOS and OS/2 linefeeds to Unix style recursively.
322              
323             =cut
324              
325             require File::Find;
326             File::Find::find(sub {
327             return if -d;
328 2 100   2 1 1250 return unless -w _;
329             return unless -r _;
330             return if -B _;
331              
332             local $\;
333              
334             my $orig = $_;
335             my $temp = '.dos2unix_tmp';
336             open ORIG, $_ or do { warn "dos2unix can't open $_: $!"; return };
337             open TEMP, ">$temp" or
338             do { warn "dos2unix can't create .dos2unix_tmp: $!"; return };
339             binmode ORIG; binmode TEMP;
340 1     1 1 205 while (my $line = <ORIG>) {
341             $line =~ s/\015\012/\012/g;
342 3 100   3   139 print TEMP $line;
343 2 50       15 }
344 2 50       12 close ORIG;
345 2 100       89 close TEMP;
346             rename $temp, $orig;
347 1         6  
348             }, @ARGV);
349 1         4 }
350 1         3  
351 1 50       25 =back
  0         0  
  0         0  
352              
353 1 50       56 =head1 SEE ALSO
  0         0  
  0         0  
354 1         4  
  1         3  
355 1         21 Shell::Command which is these same functions but take arguments normally.
356 2         9  
357 2         24  
358             =head1 AUTHOR
359 1         10  
360 1         25 Nick Ing-Simmons C<ni-s@cpan.org>
361 1         140  
362             Maintained by Michael G Schwern C<schwern@pobox.com> within the
363 1         89 ExtUtils-MakeMaker package and, as a separate CPAN package, by
364             Randy Kobes C<r.kobes@uwinnipeg.ca>.
365              
366             =cut
367