mirror of
https://github.com/borgbase/vorta
synced 2025-03-09 05:16:49 +00:00
Add option to refresh individual archives. By @rblenis (#878)
This commit is contained in:
parent
7949e80381
commit
3c0dd72205
4 changed files with 86 additions and 9 deletions
57
src/vorta/borg/info_archive.py
Normal file
57
src/vorta/borg/info_archive.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
from .borg_thread import BorgThread
|
||||||
|
from vorta.models import ArchiveModel, RepoModel
|
||||||
|
|
||||||
|
|
||||||
|
class BorgInfoArchiveThread(BorgThread):
|
||||||
|
|
||||||
|
def started_event(self):
|
||||||
|
self.app.backup_started_event.emit()
|
||||||
|
self.app.backup_progress_event.emit(self.tr('Refreshing archive...'))
|
||||||
|
|
||||||
|
def finished_event(self, result):
|
||||||
|
self.app.backup_finished_event.emit(result)
|
||||||
|
self.result.emit(result)
|
||||||
|
self.app.backup_progress_event.emit(self.tr('Refreshing archive done.'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def prepare(cls, profile, archive_name):
|
||||||
|
ret = super().prepare(profile)
|
||||||
|
if not ret['ok']:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
ret['ok'] = True
|
||||||
|
ret['cmd'] = [
|
||||||
|
'borg', 'info', '--log-json', '--json',
|
||||||
|
f'{profile.repo.url}::{archive_name}']
|
||||||
|
ret['archive_name'] = archive_name
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def process_result(self, result):
|
||||||
|
if result['returncode'] == 0:
|
||||||
|
remote_archives = result['data'].get('archives', [])
|
||||||
|
|
||||||
|
# get info stored during BorgThread.prepare()
|
||||||
|
# repo_id = self.params['repo_id']
|
||||||
|
repo_id = result['params']['repo_id']
|
||||||
|
|
||||||
|
# Update remote archives.
|
||||||
|
for remote_archive in remote_archives:
|
||||||
|
archive = ArchiveModel.get_or_none(
|
||||||
|
snapshot_id=remote_archive['id'],
|
||||||
|
repo=repo_id)
|
||||||
|
archive.name = remote_archive['name'] # incase name changed
|
||||||
|
# archive.time = parser.parse(remote_archive['time'])
|
||||||
|
archive.duration = remote_archive['duration']
|
||||||
|
archive.size = remote_archive['stats']['deduplicated_size']
|
||||||
|
|
||||||
|
archive.save()
|
||||||
|
|
||||||
|
if 'cache' in result['data']:
|
||||||
|
stats = result['data']['cache']['stats']
|
||||||
|
repo = RepoModel.get(id=result['params']['repo_id'])
|
||||||
|
repo.total_size = stats['total_size']
|
||||||
|
repo.unique_csize = stats['unique_csize']
|
||||||
|
repo.unique_size = stats['unique_size']
|
||||||
|
repo.total_unique_chunks = stats['total_unique_chunks']
|
||||||
|
repo.save()
|
|
@ -3,7 +3,7 @@ from vorta.i18n import trans_late
|
||||||
from vorta.models import RepoModel
|
from vorta.models import RepoModel
|
||||||
|
|
||||||
|
|
||||||
class BorgInfoThread(BorgThread):
|
class BorgInfoRepoThread(BorgThread):
|
||||||
|
|
||||||
def started_event(self):
|
def started_event(self):
|
||||||
self.updated.emit(self.tr('Validating existing repo...'))
|
self.updated.emit(self.tr('Validating existing repo...'))
|
|
@ -14,6 +14,7 @@ from vorta.borg.diff import BorgDiffThread
|
||||||
from vorta.borg.extract import BorgExtractThread
|
from vorta.borg.extract import BorgExtractThread
|
||||||
from vorta.borg.list_archive import BorgListArchiveThread
|
from vorta.borg.list_archive import BorgListArchiveThread
|
||||||
from vorta.borg.list_repo import BorgListRepoThread
|
from vorta.borg.list_repo import BorgListRepoThread
|
||||||
|
from vorta.borg.info_archive import BorgInfoArchiveThread
|
||||||
from vorta.borg.mount import BorgMountThread
|
from vorta.borg.mount import BorgMountThread
|
||||||
from vorta.borg.prune import BorgPruneThread
|
from vorta.borg.prune import BorgPruneThread
|
||||||
from vorta.borg.umount import BorgUmountThread
|
from vorta.borg.umount import BorgUmountThread
|
||||||
|
@ -117,10 +118,6 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
|
||||||
action.setEnabled(False)
|
action.setEnabled(False)
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
extractAction = menu.addAction("Extract", self.list_archive_action)
|
|
||||||
deleteAction = menu.addAction("Delete", self.delete_action)
|
|
||||||
renameAction = menu.addAction("Rename", self.rename_action)
|
|
||||||
|
|
||||||
if archive_name in self.mount_points:
|
if archive_name in self.mount_points:
|
||||||
unmountAction = menu.addAction("Unmount", self.umount_action)
|
unmountAction = menu.addAction("Unmount", self.umount_action)
|
||||||
unmountAction.setIcon(get_colored_icon('eject'))
|
unmountAction.setIcon(get_colored_icon('eject'))
|
||||||
|
@ -128,9 +125,15 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
|
||||||
mountAction = menu.addAction("Mount", self.mount_action)
|
mountAction = menu.addAction("Mount", self.mount_action)
|
||||||
mountAction.setIcon(get_colored_icon('folder-open'))
|
mountAction.setIcon(get_colored_icon('folder-open'))
|
||||||
|
|
||||||
|
extractAction = menu.addAction("Extract", self.list_archive_action)
|
||||||
|
refreshAction = menu.addAction("Refresh", self.refresh_archive_action)
|
||||||
|
renameAction = menu.addAction("Rename", self.rename_action)
|
||||||
|
deleteAction = menu.addAction("Delete", self.delete_action)
|
||||||
|
|
||||||
extractAction.setIcon(get_colored_icon('cloud-download'))
|
extractAction.setIcon(get_colored_icon('cloud-download'))
|
||||||
deleteAction.setIcon(get_colored_icon('trash'))
|
refreshAction.setIcon(get_colored_icon('refresh'))
|
||||||
renameAction.setIcon(get_colored_icon('edit'))
|
renameAction.setIcon(get_colored_icon('edit'))
|
||||||
|
deleteAction.setIcon(get_colored_icon('trash'))
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
def populate_from_profile(self):
|
def populate_from_profile(self):
|
||||||
|
@ -258,6 +261,23 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
|
||||||
self._set_status(self.tr('Refreshed archives.'))
|
self._set_status(self.tr('Refreshed archives.'))
|
||||||
self.populate_from_profile()
|
self.populate_from_profile()
|
||||||
|
|
||||||
|
def refresh_archive_action(self):
|
||||||
|
archive_name = self.selected_archive_name()
|
||||||
|
if archive_name is not None:
|
||||||
|
params = BorgInfoArchiveThread.prepare(self.profile(), archive_name)
|
||||||
|
if params['ok']:
|
||||||
|
thread = BorgInfoArchiveThread(params['cmd'], params, parent=self.app)
|
||||||
|
thread.updated.connect(self._set_status)
|
||||||
|
thread.result.connect(self.refresh_archive_result)
|
||||||
|
self._toggle_all_buttons(False)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
def refresh_archive_result(self, result):
|
||||||
|
self._toggle_all_buttons(True)
|
||||||
|
if result['returncode'] == 0:
|
||||||
|
self._set_status(self.tr('Refreshed archive.'))
|
||||||
|
self.populate_from_profile()
|
||||||
|
|
||||||
def selected_archive_name(self):
|
def selected_archive_name(self):
|
||||||
row_selected = self.archiveTable.selectionModel().selectedRows()
|
row_selected = self.archiveTable.selectionModel().selectedRows()
|
||||||
if row_selected:
|
if row_selected:
|
||||||
|
|
|
@ -6,7 +6,7 @@ from vorta.utils import get_private_keys, get_asset, choose_file_dialog, \
|
||||||
borg_compat, validate_passwords, display_password_backend
|
borg_compat, validate_passwords, display_password_backend
|
||||||
from vorta.keyring.abc import VortaKeyring
|
from vorta.keyring.abc import VortaKeyring
|
||||||
from vorta.borg.init import BorgInitThread
|
from vorta.borg.init import BorgInitThread
|
||||||
from vorta.borg.info import BorgInfoThread
|
from vorta.borg.info_repo import BorgInfoRepoThread
|
||||||
from vorta.i18n import translate
|
from vorta.i18n import translate
|
||||||
from vorta.views.utils import get_colored_icon
|
from vorta.views.utils import get_colored_icon
|
||||||
from vorta.models import RepoModel
|
from vorta.models import RepoModel
|
||||||
|
@ -208,10 +208,10 @@ class ExistingRepoWindow(AddRepoWindow):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.validate():
|
if self.validate():
|
||||||
params = BorgInfoThread.prepare(self.values)
|
params = BorgInfoRepoThread.prepare(self.values)
|
||||||
if params['ok']:
|
if params['ok']:
|
||||||
self.saveButton.setEnabled(False)
|
self.saveButton.setEnabled(False)
|
||||||
thread = BorgInfoThread(params['cmd'], params, parent=self)
|
thread = BorgInfoRepoThread(params['cmd'], params, parent=self)
|
||||||
thread.updated.connect(self._set_status)
|
thread.updated.connect(self._set_status)
|
||||||
thread.result.connect(self.run_result)
|
thread.result.connect(self.run_result)
|
||||||
self.thread = thread # Needs to be connected to self for tests to work.
|
self.thread = thread # Needs to be connected to self for tests to work.
|
||||||
|
|
Loading…
Add table
Reference in a new issue