summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/App/BorgRestore.pm128
1 files changed, 128 insertions, 0 deletions
diff --git a/lib/App/BorgRestore.pm b/lib/App/BorgRestore.pm
index 92faa4f..a3f4838 100644
--- a/lib/App/BorgRestore.pm
+++ b/lib/App/BorgRestore.pm
@@ -41,6 +41,8 @@ App::BorgRestore - Restore paths from borg backups
# Restore a path from a backup that is at least 5 days old. Optionally
# restore it to a different directory than the original.
+ # Look at the implementation of this method if you want to know how the
+ # other parts of this module work together.
$app->restore_simple($path, "5days", $optional_destination_directory);
=head1 DESCRIPTION
@@ -60,13 +62,29 @@ usage.
This package uses L<Log::Any> for logging.
+=head1 METHODS
+=head2 Constructors
+=head3 new
+ App::BorgRestore->new(\%deps);
+Returns a new instance. The following dependencies can be injected:
+=over
+=item * borg (optional)
+This object is used to interact with the borg repository of the system.
+Defaults to L<App::BorgRestore::Borg>
+
+=item * db (optional)
+
+This object is used to store the extracted data (the cache). Defaults to
+L<App::BorgRestore::DB>
+
+=back
=cut
@@ -83,6 +101,13 @@ method new($class: $deps = {}) {
return $self;
}
+=head3 new_no_defaults
+
+Same as C<new> except that this does not initialize unset dependencies with
+their default values. This is probably only useful for tests.
+
+=cut
+
method new_no_defaults($class: $deps) {
my $self = {};
bless $self, $class;
@@ -93,6 +118,16 @@ method new_no_defaults($class: $deps) {
return $self;
}
+=head2 Public Methods
+
+=head3 resolve_relative_path
+
+ my $abs_path = $app->resolve_relative_path($path);
+
+Returns an absolute path for a given path.
+
+=cut
+
method resolve_relative_path($path) {
my $canon_path = File::Spec->canonpath($path);
my $abs_path = abs_path($canon_path);
@@ -106,6 +141,18 @@ method resolve_relative_path($path) {
return $abs_path;
}
+=head3 map_path_to_backup_path
+
+ my $path_in_backup = $app->map_path_to_backup_path($abs_path);
+
+Maps an absolute path from the system to the path that needs to be looked up in
+/ extracted from the backup using C<@backup_prefixes> from
+L<App::BorgRestore::Settings>.
+
+Returns the mapped path (string).
+
+=cut
+
method map_path_to_backup_path($abs_path) {
my $backup_path = $abs_path;
@@ -119,6 +166,17 @@ method map_path_to_backup_path($abs_path) {
return $backup_path;
}
+=head3 find_archives
+
+ my $archives = $app->find_archives($path);
+
+Returns an arrayref of archives (hash with "modification_time" and "archive")
+from the database that contain a path. Duplicates are filtered based on the
+modification time of the path in the
+archives.
+
+=cut
+
method find_archives($path) {
my %seen_modtime;
my @ret;
@@ -145,6 +203,18 @@ method find_archives($path) {
return \@ret;
}
+=head3 get_all_archives
+
+ my $archives = $app->get_all_archives();
+
+Returns an arrayref of archives (hash with "modification_time" and "archive")
+from borg directly. This does not require the database to be populated. Instead
+it just fetches a list of archives from borg at runtime and returns it.
+
+The returned data structure is the same as that returned by C<find_archives>.
+
+=cut
+
method get_all_archives() {
#my %seen_modtime;
my @ret;
@@ -167,6 +237,18 @@ method get_all_archives() {
return \@ret;
}
+=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)) {
@@ -221,6 +303,22 @@ method _timespec_to_seconds($timespec) {
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 = App::BorgRestore::Helper::untaint($destination, qr(.*));
$path = App::BorgRestore::Helper::untaint($path, qr(.*));
@@ -244,6 +342,19 @@ method restore($path, $archive, $destination) {
$self->{borg}->restore($components_to_strip, $archive_name, $path);
}
+=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.
+
+=cut
+
method restore_simple($path, $timespec, $destination) {
my $abs_path = $self->resolve_relative_path($path);
my $backup_path = $self->map_path_to_backup_path($abs_path);
@@ -281,6 +392,14 @@ method _add_path_to_hash($hash, $path, $time) {
}
}
+=head3 get_missing_items
+
+ my $items = $app->get_missing_items($have, $want);
+
+Returns an arrayref of items that are part of C<$want>, but not of C<$have>.
+
+=cut
+
method get_missing_items($have, $want) {
my $ret = [];
@@ -366,6 +485,15 @@ method _save_node($archive_id, $prefix, $node) {
}
}
+
+=head3 update_cache
+
+ $app->update_cache();
+
+Updates the database used by e.g. C<find_archives>.
+
+=cut
+
method update_cache() {
$log->debug("Updating cache if required");