mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 01:14:15 +02:00
[backup] improvement: 'single mode' should only remove self generated snapshots
This commit is contained in:
@@ -17,6 +17,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
### Improvements
|
### Improvements
|
||||||
- General
|
- General
|
||||||
- code refactoring
|
- code refactoring
|
||||||
|
- backup:
|
||||||
|
- single mode: only removing self generated snapshots (now the snapshots are associated with the comment "<bauh>") [#244](https://github.com/vinifmor/bauh/issues/244)
|
||||||
|
|
||||||
- Arch
|
- Arch
|
||||||
- text length of some popups reduced
|
- text length of some popups reduced
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ disk:
|
|||||||
after_upgrade: false # it trims the disk after a successful packages upgrade (`fstrim -a -v`). 'true' will automatically perform the trim and 'null' will display a confirmation dialog
|
after_upgrade: false # it trims the disk after a successful packages upgrade (`fstrim -a -v`). 'true' will automatically perform the trim and 'null' will display a confirmation dialog
|
||||||
backup:
|
backup:
|
||||||
enabled: true # generate timeshift snapshots before an action (if timeshift is installed on the system)
|
enabled: true # generate timeshift snapshots before an action (if timeshift is installed on the system)
|
||||||
mode: 'incremental' # incremental=generates a new snapshot based on another pre-exising one. 'only_one'=deletes all pre-existing snapshots and generates a fresh one.
|
mode: 'incremental' # incremental=generates a new snapshot based on another pre-exising one. 'only_one'=deletes all pre-existing self created snapshots and generates a fresh one.
|
||||||
install: null # defines if the backup should be performed before installing a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
install: null # defines if the backup should be performed before installing a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
||||||
uninstall: null # defines if the backup should be performed before uninstalling a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
uninstall: null # defines if the backup should be performed before uninstalling a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
||||||
upgrade: null # defines if the backup should be performed before upgrading a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
upgrade: null # defines if the backup should be performed before upgrading a package. Allowed values: null (a dialog will be displayed asking if a snapshot should be generated), true: generates the backup without asking. false: disables the backup for this operation
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from typing import Optional
|
from typing import Optional, Generator
|
||||||
|
|
||||||
from bauh.commons.system import SimpleProcess
|
from bauh import __app_name__
|
||||||
|
from bauh.commons.system import SimpleProcess, new_root_subprocess
|
||||||
|
|
||||||
|
RE_SNAPSHOTS = re.compile(r'\d+\s+>\s+([\w\-_]+)\s+.+<{}>'.format(__app_name__))
|
||||||
|
|
||||||
|
|
||||||
def is_available() -> bool:
|
def is_available() -> bool:
|
||||||
@@ -12,5 +16,23 @@ def delete_all_snapshots(root_password: Optional[str]) -> SimpleProcess:
|
|||||||
return SimpleProcess(['timeshift', '--delete-all', '--scripted'], root_password=root_password)
|
return SimpleProcess(['timeshift', '--delete-all', '--scripted'], root_password=root_password)
|
||||||
|
|
||||||
|
|
||||||
|
def delete(snapshot_name: str, root_password: Optional[str]) -> SimpleProcess:
|
||||||
|
return SimpleProcess(('timeshift', '--delete', '--snapshot', snapshot_name),
|
||||||
|
shell=True, root_password=root_password)
|
||||||
|
|
||||||
|
|
||||||
def create_snapshot(root_password: Optional[str], mode: str) -> SimpleProcess:
|
def create_snapshot(root_password: Optional[str], mode: str) -> SimpleProcess:
|
||||||
return SimpleProcess(['timeshift', '--create', '--scripted', '--{}'.format(mode)], root_password=root_password)
|
return SimpleProcess(('timeshift', '--create', '--scripted', f'--{mode}', '--comments', f'<{__app_name__}>'),
|
||||||
|
root_password=root_password)
|
||||||
|
|
||||||
|
|
||||||
|
def read_created_snapshots(root_password: Optional[str]) -> Generator[str, None, None]:
|
||||||
|
proc = new_root_subprocess(cmd=('timeshift', '--list'), root_password=root_password, shell=True)
|
||||||
|
proc.wait()
|
||||||
|
|
||||||
|
if proc.returncode == 0:
|
||||||
|
output = '\n'.join((o.decode() for o in proc.stdout))
|
||||||
|
|
||||||
|
if output:
|
||||||
|
for name in RE_SNAPSHOTS.findall(output):
|
||||||
|
yield name
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import traceback
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Type, Set, Tuple, Optional, Iterable
|
from typing import List, Type, Set, Tuple, Optional
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from PyQt5.QtCore import QThread, pyqtSignal, QObject
|
from PyQt5.QtCore import QThread, pyqtSignal, QObject
|
||||||
@@ -140,16 +140,26 @@ class AsyncAction(QThread, ProcessWatcher):
|
|||||||
|
|
||||||
handler = ProcessHandler(self)
|
handler = ProcessHandler(self)
|
||||||
if app_config['backup']['mode'] == 'only_one':
|
if app_config['backup']['mode'] == 'only_one':
|
||||||
self.change_substatus('[{}] {}'.format(self.i18n['core.config.tab.backup'].lower(), self.i18n['action.backup.substatus.delete']))
|
previous_snapshots = tuple(timeshift.read_created_snapshots(root_password))
|
||||||
deleted, _ = handler.handle_simple(timeshift.delete_all_snapshots(root_password))
|
|
||||||
|
|
||||||
if not deleted and not self.request_confirmation(title=self.i18n['core.config.tab.backup'],
|
if previous_snapshots:
|
||||||
body='{}. {}'.format(self.i18n['action.backup.error.delete'],
|
substatus = f"[{self.i18n['core.config.tab.backup'].lower()}] {self.i18n['action.backup.substatus.delete']}"
|
||||||
self.i18n['action.backup.error.proceed']),
|
self.change_substatus(substatus)
|
||||||
confirmation_label=self.i18n['yes'].capitalize(),
|
|
||||||
deny_label=self.i18n['no'].capitalize()):
|
delete_failed = False
|
||||||
self.change_substatus('')
|
for snapshot in reversed(previous_snapshots):
|
||||||
return False
|
deleted, _ = handler.handle_simple(timeshift.delete(snapshot, root_password))
|
||||||
|
|
||||||
|
if not deleted:
|
||||||
|
delete_failed = True
|
||||||
|
|
||||||
|
if delete_failed and not self.request_confirmation(title=self.i18n['core.config.tab.backup'],
|
||||||
|
body=f"{self.i18n['action.backup.error.delete']}. "
|
||||||
|
f"{self.i18n['action.backup.error.proceed']}",
|
||||||
|
confirmation_label=self.i18n['yes'].capitalize(),
|
||||||
|
deny_label=self.i18n['no'].capitalize()):
|
||||||
|
self.change_substatus('')
|
||||||
|
return False
|
||||||
|
|
||||||
self.change_substatus('[{}] {}'.format(self.i18n['core.config.tab.backup'].lower(), self.i18n['action.backup.substatus.create']))
|
self.change_substatus('[{}] {}'.format(self.i18n['core.config.tab.backup'].lower(), self.i18n['action.backup.substatus.create']))
|
||||||
created, _ = handler.handle_simple(timeshift.create_snapshot(root_password, app_config['backup']['type']))
|
created, _ = handler.handle_simple(timeshift.create_snapshot(root_password, app_config['backup']['type']))
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ukraine
|
|||||||
United Kingdom=United Kingdom
|
United Kingdom=United Kingdom
|
||||||
United States=United States
|
United States=United States
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=It was not possible to generate a new system copy
|
||||||
action.backup.error.delete=It was not possible to delete the old system copies
|
action.backup.error.delete=It was not possible to delete all the old system copies
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Proceed anyway ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ukraine
|
|||||||
United Kingdom=United Kingdom
|
United Kingdom=United Kingdom
|
||||||
United States=United States
|
United States=United States
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=It was not possible to generate a new system copy
|
||||||
action.backup.error.delete=It was not possible to delete the old system copies
|
action.backup.error.delete=It was not possible to delete all the old system copies
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Proceed anyway ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ukraine
|
|||||||
United Kingdom=United Kingdom
|
United Kingdom=United Kingdom
|
||||||
United States=United States
|
United States=United States
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=It was not possible to generate a new system copy
|
||||||
action.backup.error.delete=It was not possible to delete the old system copies
|
action.backup.error.delete=It was not possible to delete all the old system copies
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Proceed anyway ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ucrania
|
|||||||
United Kingdom=Reino Unido
|
United Kingdom=Reino Unido
|
||||||
United States=Estados Unidos
|
United States=Estados Unidos
|
||||||
action.backup.error.create=No fue posible generar una nueva copia de seguridad
|
action.backup.error.create=No fue posible generar una nueva copia de seguridad
|
||||||
action.backup.error.delete=No fue posible eliminar las copias de seguridad antiguas del sistema
|
action.backup.error.delete=No fue posible eliminar todas las copias de seguridad antiguas del sistema
|
||||||
action.backup.error.proceed=¿Continuar de todos modos?
|
action.backup.error.proceed=¿Continuar de todos modos?
|
||||||
action.backup.invalid_mode=Modo de copia de seguridad inválido
|
action.backup.invalid_mode=Modo de copia de seguridad inválido
|
||||||
action.backup.msg=¿Desea generar una copia de seguridad del sistema antes de continuar?
|
action.backup.msg=¿Desea generar una copia de seguridad del sistema antes de continuar?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ukraine
|
|||||||
United Kingdom=United Kingdom
|
United Kingdom=United Kingdom
|
||||||
United States=United States
|
United States=United States
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=It was not possible to generate a new system copy
|
||||||
action.backup.error.delete=It was not possible to delete the old system copies
|
action.backup.error.delete=It was not possible to delete all the old system copies
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Proceed anyway ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Ucrânia
|
|||||||
United Kingdom=Reino Unido
|
United Kingdom=Reino Unido
|
||||||
United States=Estados Unidos
|
United States=Estados Unidos
|
||||||
action.backup.error.create=Não foi possível gerar uma nova cópia de segurança do sistema
|
action.backup.error.create=Não foi possível gerar uma nova cópia de segurança do sistema
|
||||||
action.backup.error.delete=Não foi possível remover as cópias de segurança antigas do sistema
|
action.backup.error.delete=Não foi possível remover todas as cópias de segurança antigas do sistema
|
||||||
action.backup.error.proceed=Continuar mesmo assim ?
|
action.backup.error.proceed=Continuar mesmo assim ?
|
||||||
action.backup.invalid_mode=Modo de cópia de segurança inválido
|
action.backup.invalid_mode=Modo de cópia de segurança inválido
|
||||||
action.backup.msg=Você deseja gerar uma cópia de segurança do sistema antes de proceder ?
|
action.backup.msg=Você deseja gerar uma cópia de segurança do sistema antes de proceder ?
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ukraine=Украина
|
|||||||
United Kingdom=Великобритания
|
United Kingdom=Великобритания
|
||||||
United States=Соединённые Штаты Америки
|
United States=Соединённые Штаты Америки
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=It was not possible to generate a new system copy
|
||||||
action.backup.error.delete=It was not possible to delete the old system copies
|
action.backup.error.delete=It was not possible to delete all the old system copies
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Proceed anyway ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
|
|||||||
Reference in New Issue
Block a user