I needed to safely update a state file (after a disk-full error caused a corruption) - added some notes here Programming_Notes/PerlProgramming/HandyModules.
These tests (which failed for IO::AtomicFile) showed me the IO::File::AtomicChange module does what I need it to do:
Test code:
use warnings; use Test::More qw(no_plan); use File::Temp qw(tempdir); use IO::File::AtomicChange; # # Checking out IO::AtomicFile # ############################################################ # Set-up # my $dir = tempdir( CLEANUP => 1 ); my $test_content = "aaa\nbbb\nccc"; my $test_filepath = "${dir}/testfile"; ############################################################ # Tests # # Create a new file my $fh = IO::File::AtomicChange->new($test_filepath, "w"); $fh->print($test_content); $fh->close(); is( slurp($test_filepath), $test_content, "Create a new file and write to it - content matches" ); # Create a new file but fail eval { my $fh = IO::File::AtomicChange->new($test_filepath, "w"); $fh->print("lose this content"); die; }; is( slurp($test_filepath), $test_content, "Start to overwrite the file but abort - no changes" ); # Update a file but fail reset_testfile(); eval { my $fh = IO::File::AtomicChange->new($test_filepath, "a"); $fh->print("lose this content"); die; }; is( slurp($test_filepath), $test_content, "Start to update the file but abort - no changes" ); # Update a file successfully reset_testfile(); my $fh = IO::File::AtomicChange->new($test_filepath, "a"); $fh->print("more"); $fh->close(); is( slurp($test_filepath), "${test_content}more", "Update the file - changes made" ); ############################################################ # Functions # sub reset_testfile { open my $fh, ">", $test_filepath or die "open failed: $!"; print $fh $test_content or die "print failed: $!"; close $fh or die "close failed: $!"; } sub slurp { open my $fh, "<", shift; local $/; <$fh> }
Test results:
$ prove -v atomic.t atomic.t .. "my" variable $fh masks earlier declaration in same scope at atomic.t line 52. ok 1 - Create a new file and write to it - content matches [CAUTION] disposed object without closing file handle. at atomic.t line 34 ok 2 - Start to overwrite the file but abort - no changes [CAUTION] disposed object without closing file handle. at atomic.t line 43 ok 3 - Start to update the file but abort - no changes ok 4 - Update the file - changes made 1..4 ok All tests successful. Files=1, Tests=4, 0 wallclock secs ( 0.04 usr 0.03 sys + 0.06 cusr 0.06 csys = 0.19 CPU) Result: PASS