App-BorgRestore
view release on metacpan or search on metacpan
script/borg-restore.pl view on Meta::CPAN
printf "\e[1;33m%s\e[0m %s\n", App::BorgRestore::Helper::format_timestamp($archive->{modification_time}), $archive->{archive};
$counter++;
}
}
fun user_select_archive ($archives) {
my $selected_archive;
if (!@$archives) {
return;
}
print_archive_list($archives);
printf "\e[0;34m%s: \e[0m", "Enter ID to restore (Enter to skip)";
my $selection = <STDIN>;
return if !defined($selection);
chomp $selection;
return unless ($selection =~ /^\d+$/ && defined(${$archives}[$selection]));
return ${$archives}[$selection];
}
sub logger_setup {
my $appender = "Screen";
$appender = "ScreenColoredLevels" if -t STDERR; ## no critic (InputOutput::ProhibitInteractiveTest)
my $conf = "
log4perl.rootLogger = INFO, screenlog
log4perl.appender.screenlog = Log::Log4perl::Appender::$appender
log4perl.appender.screenlog.stderr = 1
log4perl.appender.screenlog.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.screenlog.layout.ConversionPattern = %p %m%n
log4perl.PatternLayout.cspec.U = sub {my \@c = caller(\$_[4]); \$c[0] =~ s/::/./g; return sprintf('%s:%s', \$c[0], \$c[2]);}
";
Log::Log4perl::init( \$conf );
Log::Any::Adapter->set('Log4perl');
$SIG{__WARN__} = sub {
local $Log::Log4perl::caller_depth =
$Log::Log4perl::caller_depth + 1;
Log::Log4perl->get_logger()->warn(@_);
};
$SIG{__DIE__} = sub {
# ignore eval blocks
return if($^S);
local $Log::Log4perl::caller_depth =
$Log::Log4perl::caller_depth + 1;
Log::Log4perl->get_logger()->fatal("Uncaught exception: ".$_[0], @_[1..$#_]);
exit(2);
};
}
sub main {
logger_setup();
my %opts;
# untaint PATH because we do not expect this to be run across user boundaries
$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", "list", "quiet", "detail", "json") or pod2usage(2);
pod2usage(0) if $opts{help};
if ($opts{version}) {
printf "Version: %s\n", $App::BorgRestore::VERSION;
return 0;
}
pod2usage(-verbose => 0) if (@ARGV== 0 and !$opts{"update-cache"} and !$opts{"list"});
if ($opts{quiet}) {
my $logger = Log::Log4perl->get_logger('');
$logger->level($WARN);
}
if ($opts{debug}) {
my $logger = Log::Log4perl->get_logger('');
$logger->level($DEBUG);
Log::Log4perl->appenders()->{"screenlog"}->layout(
Log::Log4perl::Layout::PatternLayout->new("%d %8r [%-30U] %p %m%n"));
}
$app = App::BorgRestore->new();
if ($opts{"update-cache"}) {
$app->update_cache();
return 0;
}
if ($opts{"list"}) {
my @patterns = @ARGV;
push @patterns, '', if @patterns == 0;
my $json_data = {};
for my $pattern (@patterns) {
$pattern = App::BorgRestore::Helper::untaint($pattern, qr/.*/);
my $paths = $app->search_path($pattern);
for my $path (@$paths) {
my $archives; $archives = $app->find_archives($path) if $opts{detail};
if ($opts{json}) {
$json_data->{$path} = {
path => $path,
archives => $archives,
} unless defined $json_data->{$path};
} else {
printf "%s\n", $path;
print_archive_list($archives, 0) if defined $archives;
}
}
}
if ($opts{json}) {
print encode_json($json_data);
}
return 0;
}
if (!$app->cache_contains_data() && !$opts{adhoc}) {
$log->error("Cache is empty. Either the cache path is incorrect or you did not run --update yet.");
$log->error("If you did not create a cache yet, you may want to rerun with --adhoc to simply list all backups.");
return 1;
}
my @paths = @ARGV;
my $path;
my $timespec;
my $destination;
my $archives;
$path = $ARGV[0];
if (defined($opts{destination})) {
$destination = $opts{destination};
}
if (defined($opts{time})) {
$timespec = $opts{time};
}
if (@ARGV > 1) {
die "Too many arguments";
}
my $abs_path = $app->resolve_relative_path($path);
$destination = dirname($abs_path) unless defined($destination);
my $backup_path = $app->map_path_to_backup_path($abs_path);
$log->debug("Asked to restore $backup_path to $destination");
if ($opts{adhoc}) {
$archives = $app->get_all_archives();
} else {
( run in 1.009 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )