Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions src/vorta/borg/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,8 @@ def prepare(cls, profile):
]
cmd += extra_cmd_options

# Function to extend command with exclude-if-present patterns
if profile.exclude_if_present is not None:
patterns = []
for f in profile.exclude_if_present.split('\n'):
f = f.strip()
if f.startswith('[x]'):
patterns.append(f[3:].strip()) # Remove the '[x]' prefix

for pattern in patterns:
if pattern.strip():
cmd.extend(['--exclude-if-present', pattern])
for f in profile.get_exclude_if_present_files():
cmd.extend(['--exclude-if-present', f])

# Add excludes
# Partly inspired by borgmatic/borgmatic/borg/create.py
Expand Down
19 changes: 19 additions & 0 deletions src/vorta/store/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,25 @@ def get_combined_exclusion_string(self) -> str:

return excludes

def get_exclude_if_present_files(self) -> list[str]:
"""
Return the enabled 'exclude if present' file names.

Each line is stored as '[x] name' (enabled) or '[] name' (disabled). Profiles saved
before v0.10.0 have plain names without a prefix. Those were all active back then,
so they count as enabled, the same as in the exclude dialog.
"""
files = []
for line in str(self.exclude_if_present or '').split('\n'):
line = line.strip()
if line.startswith('[]'):
continue
if line.startswith('[x]'):
line = line[3:].strip()
if line:
files.append(line)
return files

class Meta:
database = DB

Expand Down
6 changes: 2 additions & 4 deletions src/vorta/views/dialogs/archive/exclude.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,8 @@ def populate_preview_tab(self):
preview = self.profile.get_combined_exclusion_string()
if self.profile.exclude_if_present:
preview += '\n# Exclude if present'
for f in self.profile.exclude_if_present.split('\n'):
f = f.strip()
if f.startswith('[x]'):
preview += '\n' + f[3:].strip()
for f in self.profile.get_exclude_if_present_files():
preview += '\n' + f
self.exclusionsPreviewText.setPlainText(preview)

def copy_preview_to_clipboard(self):
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,30 @@ def test_prepare_returns_info_level_when_metered_connection(mocker):
mocker.patch('vorta.borg.create.get_network_status_monitor', return_value=mock_monitor)
result = BorgCreateJob.prepare(default_profile)
assert result.get('level') == 'info'


def test_create_exclude_if_present():
"""Plain names saved before v0.10.0 have no [x]/[] prefix and must still be used (#2369)."""
default_profile = BackupProfileModel.get()
default_profile.exclude_if_present = '.NO_BACKUP\n[x] .nobackup\n[] CACHEDIR.TAG\n'

result = BorgCreateJob.prepare(default_profile)

cmd = result['cmd']
assert cmd.count('--exclude-if-present') == 2
assert cmd[cmd.index('.NO_BACKUP') - 1] == '--exclude-if-present'
assert cmd[cmd.index('.nobackup') - 1] == '--exclude-if-present'
assert 'CACHEDIR.TAG' not in cmd


def test_get_exclude_if_present_files():
profile = BackupProfileModel.get()

profile.exclude_if_present = None
assert profile.get_exclude_if_present_files() == []

profile.exclude_if_present = '[] .nobackup\n[] CACHEDIR.TAG'
assert profile.get_exclude_if_present_files() == []

profile.exclude_if_present = '[x] .nobackup\n.NO_BACKUP\n\n[] CACHEDIR.TAG\n[x]'
assert profile.get_exclude_if_present_files() == ['.nobackup', '.NO_BACKUP']
Loading