mirror of https://github.com/borgbase/vorta
Fix bug related to empty excludes, add version and app icon.
This commit is contained in:
parent
af453d8a6c
commit
4c375f9547
|
@ -3,5 +3,7 @@ current_version = 0.0.3
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
|
|
||||||
[bumpversion:file:vorta/__init__.py]
|
[bumpversion:file:Makefile]
|
||||||
|
[bumpversion:file:vorta.spec]
|
||||||
|
[bumpversion:file:vorta/_version.py]
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,4 @@ docs/
|
||||||
*.autosave
|
*.autosave
|
||||||
bin/
|
bin/
|
||||||
__pycache__
|
__pycache__
|
||||||
|
Makefile
|
||||||
|
|
26
README.md
26
README.md
|
@ -4,22 +4,22 @@
|
||||||
|
|
||||||
[Vorta](http://memory-alpha.wikia.com/wiki/Vorta) is a GUI for [BorgBackup](https://borgbackup.readthedocs.io). It's in alpha status and currently has the following features:
|
[Vorta](http://memory-alpha.wikia.com/wiki/Vorta) is a GUI for [BorgBackup](https://borgbackup.readthedocs.io). It's in alpha status and currently has the following features:
|
||||||
|
|
||||||
- Select and manage SSH keys
|
- [x] Select and manage SSH keys
|
||||||
- Initialize new remote Borg repositories
|
- [x] Initialize new remote Borg repositories
|
||||||
- Create new Borg snapshots (backups) from local folders
|
- [x] Create new Borg snapshots (backups) from local folders
|
||||||
- Mount existing snapshots with FUSE
|
- [x] Mount existing snapshots with FUSE
|
||||||
- Settings stored in sqlite
|
- [x] Settings stored in sqlite
|
||||||
|
- [x] Exclude options/patterns.
|
||||||
|
|
||||||
Missing features:
|
Missing features:
|
||||||
|
|
||||||
- Scheduling for background backups.
|
- [ ] Scheduling for background backups.
|
||||||
- Rule-based scheduling by time, Wifi SSID, etc.
|
- [ ] Rule-based scheduling by time, Wifi SSID, etc.
|
||||||
- Repo pruning
|
- [ ] Repo pruning
|
||||||
- Repo checking
|
- [ ] Repo checking
|
||||||
- Securely save repo password in Keychain instead of database.
|
- [ ] Securely save repo password in Keychain instead of database.
|
||||||
- Handle encrypted SSH keys
|
- [ ] Handle encrypted SSH keys
|
||||||
- Check for duplicate source dirs
|
- [ ] Check for duplicate source dirs
|
||||||
- Exclude options/patterns.
|
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
The app package under [Releases](https://github.com/borgbase/vorta/releases) should include everything. Just download, unzip and run.
|
The app package under [Releases](https://github.com/borgbase/vorta/releases) should include everything. Just download, unzip and run.
|
||||||
|
|
10
vorta.spec
10
vorta.spec
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
block_cipher = None
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
a = Analysis(['vorta/__main__.py'],
|
a = Analysis(['vorta/__main__.py'],
|
||||||
pathex=['/Users/manu/Workspace/vorta'],
|
pathex=['/Users/manu/Workspace/vorta'],
|
||||||
binaries=[
|
binaries=[
|
||||||
|
@ -35,15 +34,18 @@ exe = EXE(pyz,
|
||||||
upx=True,
|
upx=True,
|
||||||
runtime_tmpdir=None,
|
runtime_tmpdir=None,
|
||||||
console=False )
|
console=False )
|
||||||
|
|
||||||
app = BUNDLE(exe,
|
app = BUNDLE(exe,
|
||||||
name='Vorta.app',
|
name='Vorta.app',
|
||||||
icon=None,
|
icon='vorta/UI/icons/app-icon.icns',
|
||||||
bundle_identifier=None,
|
bundle_identifier='com.borgbase.client.macos',
|
||||||
info_plist={
|
info_plist={
|
||||||
'NSHighResolutionCapable': 'True',
|
'NSHighResolutionCapable': 'True',
|
||||||
'LSUIElement': '1'
|
'LSUIElement': '1',
|
||||||
|
'CFBundleShortVersionString': '0.0.3'
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Debug package. (inspired from borg)
|
# Debug package. (inspired from borg)
|
||||||
if False:
|
if False:
|
||||||
coll = COLLECT(exe,
|
coll = COLLECT(exe,
|
||||||
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
__version__ = '0.0.3'
|
|
|
@ -5,6 +5,6 @@ from vorta.tray_menu import TrayMenu
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.thread = None
|
app.thread = None
|
||||||
app.setQuitOnLastWindowClosed(False)
|
app.setQuitOnLastWindowClosed(False)
|
||||||
menu = TrayMenu(app)
|
TrayMenu(app)
|
||||||
|
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
__version__ = '0.0.3'
|
|
@ -27,15 +27,14 @@ class BorgThread(QtCore.QThread):
|
||||||
cmd[0] = meipass_borg
|
cmd[0] = meipass_borg
|
||||||
self.cmd = cmd
|
self.cmd = cmd
|
||||||
|
|
||||||
print(cmd)
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['BORG_HOSTNAME_IS_UNIQUE'] = '1'
|
env['BORG_HOSTNAME_IS_UNIQUE'] = '1'
|
||||||
if params.get('password') and params['password']:
|
if params.get('password') and params['password']:
|
||||||
env['BORG_PASSPHRASE'] = params['password']
|
env['BORG_PASSPHRASE'] = params['password']
|
||||||
|
|
||||||
|
env['BORG_RSH'] = 'ssh -oStrictHostKeyChecking=no'
|
||||||
if params.get('ssh_key') and params['ssh_key']:
|
if params.get('ssh_key') and params['ssh_key']:
|
||||||
env['BORG_RSH'] = f'ssh -i ~/.ssh/{params["ssh_key"]}'
|
env['BORG_RSH'] += f' -i ~/.ssh/{params["ssh_key"]}'
|
||||||
|
|
||||||
self.env = env
|
self.env = env
|
||||||
self.params = params
|
self.params = params
|
||||||
|
@ -93,22 +92,24 @@ class BorgThread(QtCore.QThread):
|
||||||
cmd = ['borg', 'create', '--list', '--info', '--log-json', '--json', '-C', profile.compression]
|
cmd = ['borg', 'create', '--list', '--info', '--log-json', '--json', '-C', profile.compression]
|
||||||
|
|
||||||
# Add excludes
|
# Add excludes
|
||||||
# Inspired by borgmatic/borgmatic/borg/create.py
|
# Partly inspired by borgmatic/borgmatic/borg/create.py
|
||||||
exclude_dirs = []
|
if profile.exclude_patterns is not None:
|
||||||
for p in profile.exclude_patterns.split('\n'):
|
exclude_dirs = []
|
||||||
if p.strip():
|
for p in profile.exclude_patterns.split('\n'):
|
||||||
expanded_directory = os.path.expanduser(p.strip())
|
if p.strip():
|
||||||
exclude_dirs.append(expanded_directory)
|
expanded_directory = os.path.expanduser(p.strip())
|
||||||
|
exclude_dirs.append(expanded_directory)
|
||||||
|
|
||||||
if exclude_dirs:
|
if exclude_dirs:
|
||||||
pattern_file = tempfile.NamedTemporaryFile('w')
|
pattern_file = tempfile.NamedTemporaryFile('w')
|
||||||
pattern_file.write('\n'.join(exclude_dirs))
|
pattern_file.write('\n'.join(exclude_dirs))
|
||||||
pattern_file.flush()
|
pattern_file.flush()
|
||||||
cmd.extend(['--exclude-from', pattern_file.name])
|
cmd.extend(['--exclude-from', pattern_file.name])
|
||||||
|
|
||||||
for f in profile.exclude_if_present.split('\n'):
|
if profile.exclude_if_present is not None:
|
||||||
if f.strip():
|
for f in profile.exclude_if_present.split('\n'):
|
||||||
cmd.extend(['--exclude-if-present', f.strip()])
|
if f.strip():
|
||||||
|
cmd.extend(['--exclude-if-present', f.strip()])
|
||||||
|
|
||||||
# Add repo url and source dirs.
|
# Add repo url and source dirs.
|
||||||
cmd.append(f'{profile.repo.url}::{platform.node()}-{dt.now().isoformat()}')
|
cmd.append(f'{profile.repo.url}::{platform.node()}-{dt.now().isoformat()}')
|
||||||
|
|
|
@ -29,6 +29,10 @@ class SnapshotTab(SnapshotBase, SnapshotUI):
|
||||||
|
|
||||||
self.populate()
|
self.populate()
|
||||||
|
|
||||||
|
def set_status(self, text):
|
||||||
|
self.mountErrors.setText(text)
|
||||||
|
self.mountErrors.repaint()
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
if self.profile.repo:
|
if self.profile.repo:
|
||||||
snapshots = [s for s in self.profile.repo.snapshots.select()]
|
snapshots = [s for s in self.profile.repo.snapshots.select()]
|
||||||
|
@ -61,8 +65,9 @@ class SnapshotTab(SnapshotBase, SnapshotUI):
|
||||||
if mountPoint:
|
if mountPoint:
|
||||||
cmd.append(mountPoint)
|
cmd.append(mountPoint)
|
||||||
|
|
||||||
self.set_status('Mounting snapshot into folder', 0)
|
self.set_status('Mounting snapshot into folder...')
|
||||||
thread = BorgThread(self, cmd, {})
|
params = {'password': self.profile.repo.password}
|
||||||
|
thread = BorgThread(self, cmd, params)
|
||||||
thread.updated.connect(self.mount_update_log)
|
thread.updated.connect(self.mount_update_log)
|
||||||
thread.result.connect(self.mount_get_result)
|
thread.result.connect(self.mount_get_result)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
@ -71,6 +76,5 @@ class SnapshotTab(SnapshotBase, SnapshotUI):
|
||||||
self.mountErrors.setText(text)
|
self.mountErrors.setText(text)
|
||||||
|
|
||||||
def mount_get_result(self, result):
|
def mount_get_result(self, result):
|
||||||
self.set_status(progress_max=100)
|
|
||||||
if result['returncode'] == 0:
|
if result['returncode'] == 0:
|
||||||
self.set_status('Mounted successfully.')
|
self.set_status('Mounted successfully.')
|
||||||
|
|
Loading…
Reference in New Issue