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