App-BorgRestore
view release on metacpan or search on metacpan
lib/App/BorgRestore.pm view on Meta::CPAN
=head3 cache_contains_data
if ($app->cache_contains_data()) { ... }
Returns 1 if the cache contains any archive data, 0 otherwise.
=cut
method cache_contains_data() {
my $existing_archives = $self->{deps}->{db}->get_archive_names();
return @{$existing_archives}+0 > 0 ? 1 : 0;
}
=head3 select_archive_timespec
my $archive = $app->select_archive_timespec($archives, $timespec);
Returns one archive from C<$archives> that is older than the value of
C<$timespec>.
I<timespec> is a string of the form "<I<number>><I<unit>>" with I<unit> being one of the following:
s (seconds), min (minutes), h (hours), d (days), m (months = 31 days), y (year). Example: "5.5d"
=cut
method select_archive_timespec($archives, $timespec) {
my $seconds = $self->_timespec_to_seconds($timespec);
if (!defined($seconds)) {
croak $log->errorf("Invalid time specification: %s", $timespec);
}
my $target_timestamp = time - $seconds;
$log->debugf("Searching for newest archive that contains a copy before %s", App::BorgRestore::Helper::format_timestamp($target_timestamp));
for my $archive (reverse @$archives) {
if ($archive->{modification_time} < $target_timestamp) {
$log->debugf("Found archive with timestamp %s", App::BorgRestore::Helper::format_timestamp($archive->{modification_time}));
return $archive;
}
}
die $log->error("Failed to find archive matching time specification")."\n";
}
method _timespec_to_seconds($timespec) {
if ($timespec =~ m/^(?>(?<value>[0-9.]+))(?>(?<unit>[a-z]+))$/) {
my $value = $+{value};
my $unit = $+{unit};
my %factors = (
s => 1,
second => 1,
seconds => 1,
minute => 60,
minutes => 60,
h => 60*60,
hour => 60*60,
hours => 60*60,
d => 60*60*24,
day => 60*60*24,
days => 60*60*24,
m => 60*60*24*31,
month => 60*60*24*31,
months => 60*60*24*31,
y => 60*60*24*365,
year => 60*60*24*365,
years => 60*60*24*365,
);
if (exists($factors{$unit})) {
return $value * $factors{$unit};
}
}
return;
}
=head3 restore
$app->restore($backup_path, $archive, $destination);
Restore a backup path (returned by C<map_path_to_backup_path>) from an archive
(returned by C<find_archives> or C<get_all_archives>) to a destination
directory.
If the destination path (C<$destination/$last_elem_of_backup_path>) exists, it
is removed before beginning extraction from the backup.
Warning: This method temporarily modifies the current working directory of the
process during method execution since this is required by C<`borg extract`>.
=cut
method restore($path, $archive, $destination) {
$destination = untaint($destination, qr(.*));
$path = untaint($path, qr(.*));
$log->infof("Restoring %s to %s from archive %s", $path, $destination, $archive->{archive});
my $basename = path($path)->basename;
my $components_to_strip =()= $path =~ /\//g;
$log->debugf("CWD is %s", getcwd());
{
$log->debugf("Changing CWD to %s", $destination);
mkdir($destination) unless -d $destination;
my $workdir = pushd($destination, {untaint_pattern => qr{^(.*)$}});
my $final_destination = abs_path($basename);
$final_destination = untaint($final_destination, qr(.*));
$log->debugf("Removing %s", $final_destination);
File::Path::remove_tree($final_destination);
$self->{deps}->{borg}->restore($components_to_strip, $archive->{archive}, $path);
}
$log->debugf("CWD is %s", getcwd());
}
=head3 restore_simple
$app->restore_simple($path, $timespec, $destination);
Restores a C<$path> based on a C<$timespec> to an optional C<$destination>. If
C<$destination> is not specified, it is set to the parent directory of C<$path>
so that C<$path> is restored to its original place.
Refer to L</"select_archive_timespec"> for an explanation of the C<$timespec>
variable.
( run in 1.621 second using v1.01-cache-2.11-cpan-39bf76dae61 )