diff options
-rw-r--r-- | Changes | 2 | ||||
-rw-r--r-- | lib/App/BorgRestore/DB.pm | 20 | ||||
-rw-r--r-- | t/handle_added_archives_with_db.t | 49 |
3 files changed, 64 insertions, 7 deletions
@@ -1,6 +1,8 @@ Revision history for Perl extension App-BorgRestore {{$NEXT}} + - Properly handle cases where the DB is empty after removal of archive + information 3.2.1 2018-11-01T12:54:26Z - Add missing version requirement to List::Util dependency diff --git a/lib/App/BorgRestore/DB.pm b/lib/App/BorgRestore/DB.pm index 3c9e0fb..fd8506f 100644 --- a/lib/App/BorgRestore/DB.pm +++ b/lib/App/BorgRestore/DB.pm @@ -105,21 +105,27 @@ method remove_archive($archive) { } my @columns_to_copy = map {'`'._prefix_archive_id($_).'`'} @keep_archives; + my @timestamp_columns_to_copy = @columns_to_copy; @columns_to_copy = ('`path`', @columns_to_copy); - $self->{dbh}->do('insert into `files_new` select '.join(',', @columns_to_copy).' from files'); + + if (@timestamp_columns_to_copy > 0) { + $self->{dbh}->do('insert into `files_new` select '.join(',', @columns_to_copy).' from files'); + } $self->{dbh}->do('drop table `files`'); $self->{dbh}->do('alter table `files_new` rename to `files`'); - my $sql = 'delete from `files` where '; - $sql .= join(' is null and ', grep {$_ ne '`path`' } @columns_to_copy); - $sql .= " is null"; + if (@timestamp_columns_to_copy > 0) { + my $sql = 'delete from `files` where '; + $sql .= join(' is null and ', @timestamp_columns_to_copy); + $sql .= " is null"; - my $st = $self->{dbh}->prepare($sql); - my $rows = $st->execute(); + my $st = $self->{dbh}->prepare($sql); + $st->execute(); + } - $st = $self->{dbh}->prepare('delete from `archives` where `archive_name` = ?;'); + my $st = $self->{dbh}->prepare('delete from `archives` where `archive_name` = ?;'); $st->execute($archive); } diff --git a/t/handle_added_archives_with_db.t b/t/handle_added_archives_with_db.t index 2e222b3..6fd94ea 100644 --- a/t/handle_added_archives_with_db.t +++ b/t/handle_added_archives_with_db.t @@ -42,6 +42,7 @@ for my $in_memory (0,1) { $app->_handle_added_archives(['archive-1']); # check database content + is($db->get_archive_row_count(), 15, 'correct row count (15 paths with timestamps)'); eq_or_diff($db->get_archives_for_path('.'), [{archive => 'archive-1', modification_time => undef},]); eq_or_diff($db->get_archives_for_path('boot'), [{archive => 'archive-1', modification_time => 20},]); eq_or_diff($db->get_archives_for_path('boot/foo'), [{archive => 'archive-1', modification_time => 19},]); @@ -85,6 +86,7 @@ for my $in_memory (0,1) { $app->_handle_added_archives(['archive-2']); # check database content + is($db->get_archive_row_count(), 16, 'correct row count (16 paths with timestamps)'); eq_or_diff($db->get_archives_for_path('.'), [ {archive => 'archive-1', modification_time => undef}, {archive => 'archive-2', modification_time => undef}, @@ -162,6 +164,7 @@ for my $in_memory (0,1) { $app->_handle_removed_archives(['archive-2']); # check database contents + is($db->get_archive_row_count(), 15, 'correct row count (15 paths with timestamps)'); eq_or_diff($db->get_archives_for_path('.'), [{archive => 'archive-2', modification_time => undef},]); eq_or_diff($db->get_archives_for_path('boot'), [{archive => 'archive-2', modification_time => 20},]); eq_or_diff($db->get_archives_for_path('boot/foo'), [{archive => 'archive-2', modification_time => 19},]); @@ -180,6 +183,52 @@ for my $in_memory (0,1) { eq_or_diff($db->get_archives_for_path('etc/foo/bar'), [{archive => 'archive-2', modification_time => 1},]); eq_or_diff($db->get_archives_for_path('etc/foo/blub'), [{archive => 'archive-2', modification_time => undef},]); eq_or_diff($db->get_archives_for_path('lulz'), [{archive => 'archive-2', modification_time => undef},], 'test non-existant path'); + + # run remove again. shouldn't change anything + $app->_handle_removed_archives(['archive-2']); + is($db->get_archive_row_count(), 15, 'correct row count (15 paths with timestamps)'); + eq_or_diff($db->get_archives_for_path('.'), [{archive => 'archive-2', modification_time => undef},]); + eq_or_diff($db->get_archives_for_path('boot'), [{archive => 'archive-2', modification_time => 20},]); + eq_or_diff($db->get_archives_for_path('boot/foo'), [{archive => 'archive-2', modification_time => 19},]); + eq_or_diff($db->get_archives_for_path('boot/foo/bar'), [{archive => 'archive-2', modification_time => 19},]); + eq_or_diff($db->get_archives_for_path('boot/foo/blub'), [{archive => 'archive-2', modification_time => 13},]); + eq_or_diff($db->get_archives_for_path('boot/grub'), [{archive => 'archive-2', modification_time => 20},]); + eq_or_diff($db->get_archives_for_path('boot/grub/grub.cfg'), [{archive => 'archive-2', modification_time => 8},]); + eq_or_diff($db->get_archives_for_path('boot/test1'), [{archive => 'archive-2', modification_time => 7},]); + eq_or_diff($db->get_archives_for_path('boot/test1/f1'), [{archive => 'archive-2', modification_time => 3},]); + eq_or_diff($db->get_archives_for_path('boot/test1/f2'), [{archive => 'archive-2', modification_time => 5},]); + eq_or_diff($db->get_archives_for_path('boot/test1/f3'), [{archive => 'archive-2', modification_time => 3},]); + eq_or_diff($db->get_archives_for_path('boot/test1/f4'), [{archive => 'archive-2', modification_time => 2},]); + eq_or_diff($db->get_archives_for_path('boot/test1/f5'), [{archive => 'archive-2', modification_time => 7},]); + eq_or_diff($db->get_archives_for_path('etc'), [{archive => 'archive-2', modification_time => 3},]); + eq_or_diff($db->get_archives_for_path('etc/foo'), [{archive => 'archive-2', modification_time => 2},]); + eq_or_diff($db->get_archives_for_path('etc/foo/bar'), [{archive => 'archive-2', modification_time => 1},]); + eq_or_diff($db->get_archives_for_path('etc/foo/blub'), [{archive => 'archive-2', modification_time => undef},]); + eq_or_diff($db->get_archives_for_path('lulz'), [{archive => 'archive-2', modification_time => undef},], 'test non-existant path'); + + # remove all archives from db (no overlap between archives in db and "current" archives) + $app->_handle_removed_archives(['archive-3']); + + # check database contents + is($db->get_archive_row_count(), 0, 'db should be empty'); + eq_or_diff($db->get_archives_for_path('.'), []); + eq_or_diff($db->get_archives_for_path('boot'), []); + eq_or_diff($db->get_archives_for_path('boot/foo'), []); + eq_or_diff($db->get_archives_for_path('boot/foo/bar'), []); + eq_or_diff($db->get_archives_for_path('boot/foo/blub'), []); + eq_or_diff($db->get_archives_for_path('boot/grub'), []); + eq_or_diff($db->get_archives_for_path('boot/grub/grub.cfg'), []); + eq_or_diff($db->get_archives_for_path('boot/test1'), []); + eq_or_diff($db->get_archives_for_path('boot/test1/f1'), []); + eq_or_diff($db->get_archives_for_path('boot/test1/f2'), []); + eq_or_diff($db->get_archives_for_path('boot/test1/f3'), []); + eq_or_diff($db->get_archives_for_path('boot/test1/f4'), []); + eq_or_diff($db->get_archives_for_path('boot/test1/f5'), []); + eq_or_diff($db->get_archives_for_path('etc'), []); + eq_or_diff($db->get_archives_for_path('etc/foo'), []); + eq_or_diff($db->get_archives_for_path('etc/foo/bar'), []); + eq_or_diff($db->get_archives_for_path('etc/foo/blub'), []); + eq_or_diff($db->get_archives_for_path('lulz'), []); } |