Doit
view release on metacpan or search on metacpan
lib/Doit/File.pod view on Meta::CPAN
B<Doit::File> is a L<Doit> component providing methods for file
creation. It has to be added to a script using L<Doit's add_component|Doit/add_component>:
$doit->add_component('file');
=head2 DOIT COMMANDS
The following commands are added to the Doit runner object:
=head3 file_atomic_write
$doit->file_atomic_write($filename, $code, optkey => optval ...)
Create a file I<$filename> using a code reference I<$code> in an
atomic way. This command creates a temporary file first which is used
for the writes. If no errors happen during the code execution (i.e. no
perl-level exceptions when running the code reference, and no system
errors like "no space left on device"), then the temporary file is
renamed atomically to the final destination.
The code reference takes two parameters: a filehandle to write to and
the filename of a temporary file. Don't close the filehandle;
C<file_atomic_write> takes care of closing it (and fails if something
goes wrong).
The command always returns true, as the file is normally always
written, but see the L</check_change> option below.
Options are specified as named parameters. Possible options are:
=over
=item C<< tmpdir => I<directory> >>
Change the directory where the temporary file is created. Default is
the same directory as the final destination. The directory must
already exist. Change this if a system cannot tolerate the existence
of stray temporay files, and setting the C<tmpsuffix> option (see
below) does not help. Example:
$doit->file_atomic_write('/path/to/filename', \&writer, tmpdir => '/tmp');
B<NOTE:> if the temporary file is created in another file system than
the final destination file, then the final rename is C<not> atomic
(i.e. C<File::Copy::move> is used instead of C<rename>). For example,
on many systems F</tmp> is located on a separate file system (root fs
or a special tmpfs) than the rest of the system.
=item C<< tmpsuffix => I<suffix> >>
Change the suffix used for the temporary file. Default is C<.tmp>.
Change the suffix if a system may tolerate the existence of stray
temporary files if special suffixes are used. For example, in a
directory controlled by Debian's L<run-parts(8)> programm it can help
to use C<.dpkg-tmp> as the tempory file suffix.
=item C<< mode => I<mode> >>
Set permissions of the final destination file, using the
L<perlfunc/chmod> syntax.
If not used, then the permissions would be as creating a normal
non-executable file, which usually takes L<perlfunc/umask> into
account.
=item C<< check_change => I<bool> >>
If set to a true value, then two things are done:
=over
=item * a comparison between the old file and the newly created
temporary is done, and if there's no difference, then the old file
will be left untouched
=item * if the old file was not changed, then the command returns a
false value
=back
=back
B<NOTES>
The temporary file creation is done using L<File::Temp>. The temporary
files are removed as early as possible, even in the case of
exceptions. Only left-overs may happen if the script is killed from
outside (e.g. SIGINT, SIGKILL...). A possible solution to prevent
left-overs on CTRL-C is to a define a signal handler like this:
$SIG{INT} = sub { exit };
Some of L<File::Temp>'s standard behaviors are changed here: mode is
different (see above), and C<EXLOCK> is not set.
If the C<tmpdir> option is used, then the group of the created
temporary file may differ as it was created in the final destination
directory (e.g. in presence of setgid bits, or on BSD systems if the
directory belongs to another group). Some precautions are made to fix
this, at least for some common operating systems, but this is far from
perfect.
While running this function two versions of the file will exist
simultaneously on the disk: the old version (if it's an overwrite) and
the new version. This may be problematic if the files are large and
the diskspace limited.
The C<tmpdir> option may be set to F</dev/full>; in this case the
temporary file will be set to F</dev/full>. This is only useful in
test scripts for testing the C<ENOSPC> (see L<errno(3)> or
L<errno(2)>) case.
Special handling is implemented for older perls (5.8.x), as a failing
L<close|perlfunc/close> is not correctly detected here.
=head2 TODO
=over
=item Catch signals for temporary file cleanup?
( run in 1.488 second using v1.01-cache-2.11-cpan-39bf76dae61 )