diff options
author | Florian Pritz <bluewind@xinu.at> | 2017-05-28 20:42:57 +0200 |
---|---|---|
committer | Florian Pritz <bluewind@xinu.at> | 2017-05-28 20:42:57 +0200 |
commit | 636b361a019ab4e4b4f3960d2aeca33b7be7a8cb (patch) | |
tree | 568742918b653b5d0b084bd3be0ff53b4f08ca72 | |
parent | 511041a2b76cea1f82686e221f28ce916e73ab4f (diff) | |
download | App-BorgRestore-636b361a019ab4e4b4f3960d2aeca33b7be7a8cb.tar.gz App-BorgRestore-636b361a019ab4e4b4f3960d2aeca33b7be7a8cb.tar.xz |
Add --adhoc
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r-- | lib/App/BorgRestore.pm | 23 | ||||
-rw-r--r-- | lib/App/BorgRestore/Borg.pm | 23 | ||||
-rw-r--r-- | lib/App/BorgRestore/Helper.pm | 9 | ||||
-rwxr-xr-x | script/borg-restore.pl | 19 |
4 files changed, 72 insertions, 2 deletions
diff --git a/lib/App/BorgRestore.pm b/lib/App/BorgRestore.pm index fe4291f..87c1311 100644 --- a/lib/App/BorgRestore.pm +++ b/lib/App/BorgRestore.pm @@ -160,6 +160,28 @@ method find_archives($path) { return \@ret; } +method get_all_archives() { + #my %seen_modtime; + my @ret; + + $log->debugf("Fetching list of all archives"); + + my $archives = $self->{borg}->borg_list_time(); + + for my $archive (@$archives) { + push @ret, $archive; + } + + if (!@ret) { + $log->errorf("No archives found.\n"); + die "No archives found.\n"; + } + + @ret = sort { $a->{modification_time} <=> $b->{modification_time} } @ret; + + return \@ret; +} + method select_archive_timespec($archives, $timespec) { my $seconds = $self->_timespec_to_seconds($timespec); if (!defined($seconds)) { @@ -323,6 +345,7 @@ method _handle_added_archives($borg_archives) { my $line = shift; # roll our own parsing of timestamps for speed since we will be parsing # a huge number of lines here + # XXX: this also exists in BorgRestore::Helper::parse_borg_time() # example timestamp: "Wed, 2016-01-27 10:31:59" if ($line =~ m/^.{4} (?<year>....)-(?<month>..)-(?<day>..) (?<hour>..):(?<minute>..):(?<second>..) (?<path>.+)$/) { my $time = POSIX::mktime($+{second},$+{minute},$+{hour},$+{day},$+{month}-1,$+{year}-1900); diff --git a/lib/App/BorgRestore/Borg.pm b/lib/App/BorgRestore/Borg.pm index c1774d7..660eb8e 100644 --- a/lib/App/BorgRestore/Borg.pm +++ b/lib/App/BorgRestore/Borg.pm @@ -3,6 +3,8 @@ use v5.10; use warnings; use strict; +use App::BorgRestore::Helper; + use Function::Parameters; use IPC::Run qw(run start new_chunker); use Log::Any qw($log); @@ -31,6 +33,27 @@ method borg_list() { return \@archives; } +method borg_list_time() { + my @archives; + + $log->debug("Getting archive list"); + run [qw(borg list), $self->{borg_repo}], '>', \my $output or die "borg list returned $?"; + + for (split/^/, $output) { + if (m/^([^\s]+)\s+(.+)$/) { + my $time = App::BorgRestore::Helper::parse_borg_time($2); + if ($time) { + push @archives, { + "archive" => $1, + "modification_time" => $time, + }; + } + } + } + + return \@archives; +} + method restore($components_to_strip, $archive_name, $path) { $log->debugf("Restoring '%s' from archive %s, stripping %d components of the path", $path, $archive_name, $components_to_strip); system(qw(borg extract -v --strip-components), $components_to_strip, $self->{borg_repo}."::".$archive_name, $path); diff --git a/lib/App/BorgRestore/Helper.pm b/lib/App/BorgRestore/Helper.pm index 976ef54..ec76926 100644 --- a/lib/App/BorgRestore/Helper.pm +++ b/lib/App/BorgRestore/Helper.pm @@ -19,6 +19,15 @@ fun format_timestamp($timestamp) { return POSIX::strftime "%a. %F %H:%M:%S %z", localtime $timestamp; } +# XXX: this also exists in BorgRestore::_handle_added_archives() +fun parse_borg_time($string) { + if ($string =~ m/^.{4} (?<year>....)-(?<month>..)-(?<day>..) (?<hour>..):(?<minute>..):(?<second>..)$/) { + my $time = POSIX::mktime($+{second},$+{minute},$+{hour},$+{day},$+{month}-1,$+{year}-1900); + return $time; + } + return; +} + 1; __END__ diff --git a/script/borg-restore.pl b/script/borg-restore.pl index dff013f..923732b 100755 --- a/script/borg-restore.pl +++ b/script/borg-restore.pl @@ -17,6 +17,8 @@ borg-restore.pl [options] <path> --destination, -d <path> Restore backup to directory <path> --time, -t <timespec> Automatically find newest backup that is at least <time spec> old + --adhoc Do not use the cache, instead provide an + unfiltered list of archive to choose from Time spec: Select the newest backup that is at least <time spec> old. @@ -70,6 +72,14 @@ Automatically find the newest backup that is at least as old as I<timespec> specifies. 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 +=item B<--adhoc> + +Disable usage of the database. In this mode, the list of archives is fetched +directly from borg at run time. Use this when the cache has not been created +yet and you want to restore a file without having to manually call borg +extract. Using this option will show all archives that borg knows about, even +if they do not contain the file that shall be restored. + =back =head1 CONFIGURATION @@ -183,7 +193,7 @@ sub main { $ENV{PATH} = App::BorgRestore::Helper::untaint($ENV{PATH}, qr(.*)); Getopt::Long::Configure ("bundling"); - GetOptions(\%opts, "help|h", "debug", "update-cache|u", "destination|d=s", "time|t=s") or pod2usage(2); + GetOptions(\%opts, "help|h", "debug", "update-cache|u", "destination|d=s", "time|t=s", "adhoc") or pod2usage(2); pod2usage(0) if $opts{help}; if ($opts{debug}) { @@ -207,6 +217,7 @@ sub main { my $path; my $timespec; my $destination; + my $archives; $path = $ARGV[0]; @@ -229,7 +240,11 @@ sub main { $log->debug("Asked to restore $backup_path to $destination"); - my $archives = $app->find_archives($backup_path); + if ($opts{adhoc}) { + $archives = $app->get_all_archives(); + } else { + $archives = $app->find_archives($backup_path); + } my $selected_archive; if (defined($timespec)) { |