summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2018-01-24 01:10:15 +0100
committerFlorian Pritz <bluewind@xinu.at>2018-01-24 01:10:15 +0100
commitd28bcb7e09769e6eaf9e4e9f0206fdc9e76a575a (patch)
treea5ea3f8bc80e94cec074f5f12107835e163db936
parentff87476fe745ecafcafe779241469b5617831c27 (diff)
downloadApp-BorgRestore-d28bcb7e09769e6eaf9e4e9f0206fdc9e76a575a.tar.gz
App-BorgRestore-d28bcb7e09769e6eaf9e4e9f0206fdc9e76a575a.tar.xz
Add --list feature to search for files contained in backups by path
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r--lib/App/BorgRestore.pm15
-rw-r--r--lib/App/BorgRestore/DB.pm16
-rwxr-xr-xscript/borg-restore.pl27
3 files changed, 56 insertions, 2 deletions
diff --git a/lib/App/BorgRestore.pm b/lib/App/BorgRestore.pm
index 828838c..c3b37fd 100644
--- a/lib/App/BorgRestore.pm
+++ b/lib/App/BorgRestore.pm
@@ -402,6 +402,21 @@ method _add_path_to_hash($hash, $path, $time) {
}
}
+=head3 search_path
+
+ my $paths = $app->search_path($pattern)
+
+Returns a arrayref of paths that match the pattern. The pattern is matched as
+an sqlite LIKE pattern. If no % occurs in the pattern, the patterns is
+automatically wrapped between two % so it may match anywhere in the path.
+
+=cut
+
+method search_path($pattern) {
+ $pattern = '%'.$pattern.'%' if $pattern !~ m/%/;
+ return $self->{db}->search_path($pattern);
+}
+
=head3 get_missing_items
my $items = $app->get_missing_items($have, $want);
diff --git a/lib/App/BorgRestore/DB.pm b/lib/App/BorgRestore/DB.pm
index 3fddbf1..1f1427e 100644
--- a/lib/App/BorgRestore/DB.pm
+++ b/lib/App/BorgRestore/DB.pm
@@ -177,6 +177,22 @@ method verify_cache_fill_rate_ok() {
}
}
+method search_path($pattern) {
+ $log->debugf("Preparing path search for pattern '%s'", $pattern);
+ my $st = $self->{dbh}->prepare('select path from files where path like ?');
+ $log->debug("Executing search");
+ $st->execute($pattern);
+ $log->debug("Fetching search result");
+
+ my @ret;
+ while (my $row = $st->fetchrow_hashref()) {
+ push @ret, $row->{path};
+ }
+
+ $log->debugf("Found %d matching paths", 0+@ret);
+ return \@ret;
+}
+
method vacuum() {
$self->{dbh}->do("vacuum");
}
diff --git a/script/borg-restore.pl b/script/borg-restore.pl
index f58ba33..76216dc 100755
--- a/script/borg-restore.pl
+++ b/script/borg-restore.pl
@@ -14,6 +14,8 @@ borg-restore.pl [options] <path>
--help, -h short help message
--debug show debug messages
--update-cache, -u update cache files
+ --list [pattern] List paths contained in the backups, optionally
+ matching an SQLite LIKE pattern
--destination, -d <path> Restore backup to directory <path>
--time, -t <timespec> Automatically find newest backup that is at least
<time spec> old
@@ -73,6 +75,12 @@ Enable debug messages.
Update the lookup database. You should run this after creating or removing a backup.
+=item B<--list> B<[pattern]>
+
+List paths contained in the backups, optionally matching an SQLite LIKE
+pattern. If no % occurs in the pattern, the patterns is automatically wrapped
+between two % so it may match anywhere in the path.
+
=item B<--destination=>I<path>, B<-d >I<path>
Restore the backup to 'path' instead of its original location. The destination
@@ -211,7 +219,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", "adhoc", "version") or pod2usage(2);
+ GetOptions(\%opts, "help|h", "debug", "update-cache|u", "destination|d=s", "time|t=s", "adhoc", "version", "list") or pod2usage(2);
pod2usage(0) if $opts{help};
if ($opts{version}) {
@@ -219,7 +227,7 @@ sub main {
return 0;
}
- pod2usage(-verbose => 0) if (@ARGV== 0 and !$opts{"update-cache"});
+ pod2usage(-verbose => 0) if (@ARGV== 0 and !$opts{"update-cache"} and !$opts{"list"});
if ($opts{debug}) {
my $logger = Log::Log4perl->get_logger('');
@@ -235,6 +243,21 @@ sub main {
return 0;
}
+ if ($opts{"list"}) {
+ my @patterns = @ARGV;
+ push @patterns, '', if @patterns == 0;
+
+ for my $pattern (@patterns) {
+ $pattern = App::BorgRestore::Helper::untaint($pattern, qr/.*/);
+
+ my $paths = $app->search_path($pattern);
+ for my $path (@$paths) {
+ printf "%s\n", $path;
+ }
+ }
+ return 0;
+ }
+
if (!$app->cache_contains_data()) {
$opts{"adhoc"} = 1;
$log->warning("Cache is empty. --adhoc has been enabled for you automatically");