Skip to content

Commit

Permalink
feat: support multiple exclude pattern for restore operation (#182)
Browse files Browse the repository at this point in the history
## Contributing process

- [X] I understand that this is [some guy's personal hobby
project](https://github.com/mtlynch/resticpy#resticpys-scope-and-future)
and reviews are on a best-effort basis
- [X] I've read the [contribution
guidelines](../blob/master/CONTRIBUTING.md)

## What type of PR is this? (check all applicable)

- [X] Feature

## Description

This PR will actually support multiple `exclude` patterns for the
`restore` operation. Before, only **one** exclude pattern can be
provided, now, similarly to the `rewrite` API, multiple exclude patterns
can be provided as a list.

## Did you update the [API documentation](../blob/master/docs)?

- [x] Yes

## Have you added or updated tests?

- [X] Yes, I added unit tests

---------

Co-authored-by: Michael Lynch <[email protected]>
  • Loading branch information
S0obi and mtlynch authored Oct 5, 2024
1 parent eb98385 commit 1e50920
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ Restores a snapshot from the repository to the specified path.

- `snapshot_id`: ID of snapshot to restore (default: `latest`)
- `include`: String specifying a pattern to include, exclude everything else
- `exclude`: A list of file patterns to exclude from restore operation
- `target_dir`: String specifying output directory to place restored data

### Returns
Expand Down
15 changes: 14 additions & 1 deletion restic/internal/restore.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from restic.internal import command_executor


class Error(Exception):
pass


class LegacySemanticsError(Error):
pass


def run(restic_base_command,
snapshot_id='latest',
include=None,
Expand All @@ -12,7 +20,12 @@ def run(restic_base_command,
cmd.extend(['--include', include])

if exclude:
cmd.extend(['--exclude', exclude])
if isinstance(exclude, str):
raise LegacySemanticsError(
'As of resticpy 1.2.0, the `exclude` parameter must be a list '
'not a string')
for exclude_path in exclude:
cmd.extend(['--exclude', exclude_path])

if target_dir:
cmd.extend(['--target', target_dir])
Expand Down
21 changes: 19 additions & 2 deletions restic/internal/restore_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,27 @@ def test_restore_specific_snapshot_id_and_include(self, mock_execute):
'include-path'
])

def test_restore_exclude_string_instead_of_list(self):
with self.assertRaises(restore.LegacySemanticsError):
restic.restore(snapshot_id='dummy-snapshot-id',
exclude='exclude-path')

@mock.patch.object(restore.command_executor, 'execute')
def test_restore_specific_snapshot_id_and_exclude(self, mock_execute):
restic.restore(snapshot_id='dummy-snapshot-id', exclude='exclude-path')
def test_restore_specific_snapshot_id_and_exclude_single_paths(
self, mock_execute):
restic.restore(snapshot_id='dummy-snapshot-id',
exclude=['exclude-path'])
mock_execute.assert_called_with([
'restic', '--json', 'restore', 'dummy-snapshot-id', '--exclude',
'exclude-path'
])

@mock.patch.object(restore.command_executor, 'execute')
def test_restore_specific_snapshot_id_and_exclude_multiple_paths(
self, mock_execute):
restic.restore(snapshot_id='dummy-snapshot-id',
exclude=['exclude-path', 'another-path'])
mock_execute.assert_called_with([
'restic', '--json', 'restore', 'dummy-snapshot-id', '--exclude',
'exclude-path', '--exclude', 'another-path'
])

0 comments on commit 1e50920

Please sign in to comment.