Skip to content

Commit

Permalink
Merge branch 'borgbase:master' into duplicate-sources-on-overwrite-bo…
Browse files Browse the repository at this point in the history
  • Loading branch information
shivansh02 committed Jun 7, 2024
2 parents 164c906 + f252a8e commit 75f6e54
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 13 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to use for building macOS release'
description: 'Branch to use for building release'
required: true
default: 'master'
borg_version:
description: 'Borg version to package'
required: true
default: '1.2.1'
default: '1.2.8'
macos_version:
description: 'macOS version for building'
required: true
default: 'macos-11'

jobs:
build:
runs-on: macos-11
runs-on: ${{ github.event.inputs.macos_version }}

steps:
- name: Check out selected branch
Expand Down
5 changes: 4 additions & 1 deletion .github/stale.yml → .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ on:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
with:
days-before-issue-stale: 60
days-before-issue-stale: 90
days-before-pr-stale: -1
days-before-issue-close: 7
# days-before-pr-close: 10
Expand Down
64 changes: 63 additions & 1 deletion src/vorta/assets/exclusion_presets/dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"patterns":
[
"fm:*/node_modules",
"fm:*/.npm"
"fm:*/.npm",
"fm:*/npm-global"
],
"tags": ["type:dev", "lang:javascript", "os:linux", "os:darwin"],
"author": "Divi"
Expand Down Expand Up @@ -33,5 +34,66 @@
],
"tags": ["type:dev", "lang:rust", "os:linux", "os:darwin"],
"author": "Divi"
},
{
"name": "Visual Studio Code cache and config files",
"slug": "vscode-cache",
"patterns": [
"fm:*/.config/Code",
"fm:*/.vscode/extensions/*"
],
"tags": ["type:editor", "editor:vscode", "os:linux"],
"author": "shivansh02"
},
{
"name": "Android Studio Artefacts",
"slug": "android-studio",
"patterns": [
"fm:*/.android",
"fm:*/.gradle",
"fm:*/Android/Sdk",
"fm:*/.AndroidStudio"
],
"tags": ["type:dev", "editor:android-studio", "os:linux"],
"author": "shivansh02"
},
{
"name": "Jetbrains IDEs cache, config, path and logs",
"slug": "jetbrains",
"patterns": [
"fm:*/.config/JetBrains",
"fm:*/.cache/JetBrains",
"fm:*/.local/share/JetBrains"
],
"tags": ["type:dev", "editor:jetbrains", "os:linux"],
"author": "SAMAD101"
},
{
"name": "AWS artefacts",
"slug": "aws-artefacts",
"patterns": [
"fm:*/.aws"
],
"tags": ["type:dev", "cloud:aws", "os:linux", "os:darwin"],
"author": "SAMAD101"
},
{
"name": "Spotify cache and config files",
"slug": "spotify",
"patterns": [
"fm:*/.cache/spotify",
"fm:*/.config/spotify"
],
"tags": ["type:media", "media:spotify", "os:linux"],
"author": "SAMAD101"
},
{
"name": "Docker artefacts",
"slug": "docker-artefacts",
"patterns": [
"fm:*/.docker"
],
"tags": ["type:dev", "cloud:docker", "os:linux", "os:darwin"],
"author": "SAMAD101"
}
]
6 changes: 6 additions & 0 deletions src/vorta/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def post_backup_tasks(self, profile_id):
Pruning and checking after successful backup.
"""
profile = BackupProfileModel.get(id=profile_id)
notifier = VortaNotifications.pick()
logger.info('Doing post-backup jobs for %s', profile.name)
if profile.prune_on:
msg = BorgPruneJob.prepare(profile)
Expand Down Expand Up @@ -489,6 +490,11 @@ def post_backup_tasks(self, profile_id):
self.app.jobs_manager.add_job(job)

logger.info('Finished background task for profile %s', profile.name)
notifier.deliver(
self.tr('Vorta Backup'),
self.tr('Post Backup Tasks successful for %s' % profile.name),
level='info',
)

def remove_job(self, profile_id):
if profile_id in self.timers:
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/tray_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def build_menu(self):
profiles = BackupProfileModel.select()
if profiles.count() > 1:
profile_menu = menu.addMenu(self.tr('Backup Now'))
for profile in profiles:
for profile in sorted(profiles, key=lambda p: (p.name.casefold(), p.name)):
new_item = profile_menu.addAction(profile.name)
new_item.triggered.connect(lambda state, i=profile.id: self.app.create_backup_action(i))
else:
Expand Down
3 changes: 3 additions & 0 deletions src/vorta/views/diff_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,13 @@ def change_display_mode(self, selection: int):
"""
if selection == 0:
mode = FileTreeModel.DisplayMode.TREE
self.bCollapseAll.setEnabled(True)
elif selection == 1:
mode = FileTreeModel.DisplayMode.SIMPLIFIED_TREE
self.bCollapseAll.setEnabled(True)
elif selection == 2:
mode = FileTreeModel.DisplayMode.FLAT
self.bCollapseAll.setEnabled(False)
else:
raise Exception("Unknown item in comboBoxDisplayMode with index {}".format(selection))

Expand Down
2 changes: 2 additions & 0 deletions src/vorta/views/extract_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,10 @@ def change_display_mode(self, selection: int):
"""
if selection == 0:
mode = FileTreeModel.DisplayMode.TREE
self.bCollapseAll.setEnabled(True)
elif selection == 1:
mode = FileTreeModel.DisplayMode.SIMPLIFIED_TREE
self.bCollapseAll.setEnabled(True)
else:
raise Exception("Unknown item in comboBoxDisplayMode with index {}".format(selection))

Expand Down
21 changes: 16 additions & 5 deletions src/vorta/views/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def __init__(self, parent=None):
prev_profile_id = SettingsModel.get(key='previous_profile_id')
self.current_profile = BackupProfileModel.get_or_none(id=prev_profile_id.str_value)
if self.current_profile is None:
self.current_profile = BackupProfileModel.select().order_by('name').first()
profiles = BackupProfileModel.select()
self.current_profile = min(profiles, key=lambda p: (p.name.casefold(), p.name))

# Load tab models
self.repoTab = RepoTab(self.repoTabSlot)
Expand Down Expand Up @@ -161,7 +162,8 @@ def populate_profile_selector(self):
current_item = None

# Add items to the QListWidget
for profile in BackupProfileModel.select().order_by(BackupProfileModel.name):
profiles = BackupProfileModel.select()
for profile in sorted(profiles, key=lambda p: (p.name.casefold(), p.name)):
item = QListWidgetItem(profile.name)
item.setData(Qt.ItemDataRole.UserRole, profile.id)

Expand Down Expand Up @@ -284,13 +286,22 @@ def profile_imported_event(profile):
def profile_add_edit_result(self, profile_name, profile_id):
# Profile is renamed
if self.profileSelector.currentItem().data(Qt.ItemDataRole.UserRole) == profile_id:
self.profileSelector.currentItem().setText(profile_name)
profile = self.profileSelector.takeItem(self.profileSelector.currentRow())
profile.setText(profile_name)
# Profile is added
else:
profile = QListWidgetItem(profile_name)
profile.setData(Qt.ItemDataRole.UserRole, profile_id)
self.profileSelector.addItem(profile)
self.profileSelector.setCurrentItem(profile)
# Insert the profile at the correct position
# Both the casefolded and the original name are used as the key to keep the order stable
profile_key = (profile.text().casefold(), profile.text())
row = 0
for i in range(self.profileSelector.count()):
item_name = self.profileSelector.item(i).text()
if (item_name.casefold(), item_name) < profile_key:
row += 1
self.profileSelector.insertItem(row, profile)
self.profileSelector.setCurrentItem(profile)

def toggle_misc_visibility(self):
if self.miscWidget.isVisible():
Expand Down
6 changes: 6 additions & 0 deletions src/vorta/views/partials/password_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,9 @@ def create_form_widget(self, parent: Optional[QWidget] = None) -> QWidget:
self.add_form_to_layout(form_layout)
widget.setLayout(form_layout)
return widget

def set_visibility(self, visible: bool) -> None:
self._label_password.setVisible(visible)
self._label_confirm.setVisible(visible)
self.passwordLineEdit.setVisible(visible)
self.confirmLineEdit.setVisible(visible)
2 changes: 2 additions & 0 deletions src/vorta/views/repo_add_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,10 @@ def encryption_listener(self):
'''Validates passwords only if its going to be used'''
if self.values['encryption'] == 'none':
self.passwordInput.set_validation_enabled(False)
self.passwordInput.set_visibility(False)
else:
self.passwordInput.set_validation_enabled(True)
self.passwordInput.set_visibility(True)

def display_backend_warning(self):
'''Display password backend message based off current keyring'''
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
import vorta.views.archive_tab
from PyQt6.QtCore import QDateTime, QItemSelectionModel, Qt
from PyQt6.QtWidgets import QMenu
from vorta.store.models import ArchiveModel
from vorta.views.diff_result import (
ChangeType,
DiffData,
DiffResultDialog,
DiffTree,
FileType,
parse_diff_json,
parse_diff_lines,
)
from vorta.views.partials.treemodel import FileTreeModel


def setup_diff_result_window(qtbot, mocker, tab, borg_json_output, json_mock_file="diff_archives"):
Expand Down Expand Up @@ -457,3 +460,19 @@ def test_archive_diff_json_parser(line, expected):

assert item.path == PurePath(expected[0]).parts
assert item.data == DiffData(*expected[1:])


@pytest.mark.parametrize(
"selection, expected_mode, expected_bCollapseAllEnabled",
[
(0, FileTreeModel.DisplayMode.TREE, True),
(1, FileTreeModel.DisplayMode.SIMPLIFIED_TREE, True),
(2, FileTreeModel.DisplayMode.FLAT, False),
],
)
def test_change_display_mode(selection: int, expected_mode, expected_bCollapseAllEnabled):
dialog = DiffResultDialog(ArchiveModel(), ArchiveModel(), DiffTree())
dialog.change_display_mode(selection)

assert dialog.model.mode == expected_mode
assert dialog.bCollapseAll.isEnabled() == expected_bCollapseAllEnabled
24 changes: 22 additions & 2 deletions tests/unit/test_extract.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import pytest
import vorta.borg
from PyQt6.QtCore import QModelIndex, Qt
from vorta.views.extract_dialog import ExtractTree, FileData, FileType, parse_json_lines
from vorta.views.partials.treemodel import FileSystemItem
from vorta.store.models import ArchiveModel
from vorta.views.extract_dialog import (
ExtractDialog,
ExtractTree,
FileData,
FileType,
parse_json_lines,
)
from vorta.views.partials.treemodel import FileSystemItem, FileTreeModel


def prepare_borg(mocker, borg_json_output):
Expand Down Expand Up @@ -177,3 +185,15 @@ def test_selection():

select(model, iab)
assert a.data.checkstate == Qt.CheckState(1)


@pytest.mark.parametrize(
"selection, expected_mode, expected_bCollapseAllEnabled",
[(0, FileTreeModel.DisplayMode.TREE, True), (1, FileTreeModel.DisplayMode.SIMPLIFIED_TREE, True)],
)
def test_change_display_mode(selection: int, expected_mode, expected_bCollapseAllEnabled):
dialog = ExtractDialog(ArchiveModel(), ExtractTree())
dialog.change_display_mode(selection)

assert dialog.model.mode == expected_mode
assert dialog.bCollapseAll.isEnabled() == expected_bCollapseAllEnabled

0 comments on commit 75f6e54

Please sign in to comment.