mirror of
https://github.com/borgbase/vorta
synced 2024-12-21 23:33:13 +00:00
Specify archive using -a
for borg v2 mount
.
* src/vorta/views/archive_tab.py : Move all command building logic into `mount.py`. * src/vorta/borg/mount.py (BorgMountJob.prepare): Add command building logic previously in other places. * src/vorta/borg/mount.py (BorgMountJob.prepare): Use `-a` command line option to select a single archive. * src/vorta/utils.py (SHELL_PATTERN_ELEMENT): A pattern that can be used to detect shell pattern syntax. * src/vorta/utils.py (get_mount_points): Implement parsing a borg v2 cmd.
This commit is contained in:
parent
b4a7c5494e
commit
5e046386d7
3 changed files with 58 additions and 28 deletions
|
@ -1,15 +1,18 @@
|
|||
import logging
|
||||
import os
|
||||
from vorta.store.models import SettingsModel
|
||||
from vorta.utils import borg_compat
|
||||
from vorta.utils import SHELL_PATTERN_ELEMENT, borg_compat
|
||||
from .borg_job import BorgJob
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BorgMountJob(BorgJob):
|
||||
def started_event(self):
|
||||
self.updated.emit(self.tr('Mounting archive into folder…'))
|
||||
|
||||
@classmethod
|
||||
def prepare(cls, profile):
|
||||
def prepare(cls, profile, archive: str = None):
|
||||
ret = super().prepare(profile)
|
||||
if not ret['ok']:
|
||||
return ret
|
||||
|
@ -26,8 +29,21 @@ def prepare(cls, profile):
|
|||
|
||||
if borg_compat.check('V2'):
|
||||
cmd.extend(["-r", profile.repo.url])
|
||||
|
||||
if archive:
|
||||
# in shell patterns ?, * and [...] have a special meaning
|
||||
pattern = SHELL_PATTERN_ELEMENT.sub(r'\\1', archive) # escape them
|
||||
cmd.extend(['-a', pattern])
|
||||
else:
|
||||
cmd.append(f'{profile.repo.url}')
|
||||
source = f'{profile.repo.url}'
|
||||
|
||||
if archive:
|
||||
source += f'::{archive}'
|
||||
|
||||
cmd.append(source)
|
||||
|
||||
if archive:
|
||||
ret['mounted_archive'] = archive
|
||||
|
||||
ret['ok'] = True
|
||||
ret['cmd'] = cmd
|
||||
|
|
|
@ -358,6 +358,9 @@ def format_archive_name(profile, archive_name_tpl):
|
|||
return archive_name_tpl.format(**available_vars)
|
||||
|
||||
|
||||
SHELL_PATTERN_ELEMENT = re.compile(r'([?\[\]*])')
|
||||
|
||||
|
||||
def get_mount_points(repo_url):
|
||||
mount_points = {}
|
||||
repo_mounts = []
|
||||
|
@ -368,23 +371,41 @@ def get_mount_points(repo_url):
|
|||
if 'mount' not in proc.cmdline():
|
||||
continue
|
||||
|
||||
for idx, parameter in enumerate(proc.cmdline()):
|
||||
if parameter.startswith(repo_url):
|
||||
# mount from this repo
|
||||
if borg_compat.check('V2'):
|
||||
# command line syntax:
|
||||
# `borg mount -r <repo> <mountpoint> <path> (-a <archive_pattern>)`
|
||||
cmd = proc.cmdline()
|
||||
if repo_url in cmd:
|
||||
i = cmd.index(repo_url)
|
||||
if len(cmd) > i + 1:
|
||||
mount_point = cmd[i + 1]
|
||||
|
||||
# The borg mount command specifies that the mount_point
|
||||
# parameter comes after the archive name
|
||||
if len(proc.cmdline()) > idx + 1:
|
||||
mount_point = proc.cmdline()[idx + 1]
|
||||
|
||||
# archive or full mount?
|
||||
if parameter[len(repo_url) :].startswith('::'):
|
||||
archive_name = parameter[len(repo_url) + 2 :]
|
||||
mount_points[archive_name] = mount_point
|
||||
break
|
||||
# Archive mount?
|
||||
ao = '-a' in cmd
|
||||
if ao or '--glob-archives' in cmd:
|
||||
i = cmd.index('-a' if ao else '--glob-archives')
|
||||
if len(cmd) >= i + 1 and not SHELL_PATTERN_ELEMENT.search(cmd[i + 1]):
|
||||
mount_points[mount_point] = cmd[i + 1]
|
||||
else:
|
||||
# repo mount point
|
||||
repo_mounts.append(mount_point)
|
||||
else:
|
||||
for idx, parameter in enumerate(proc.cmdline()):
|
||||
if parameter.startswith(repo_url):
|
||||
# mount from this repo
|
||||
|
||||
# The borg mount command specifies that the mount_point
|
||||
# parameter comes after the archive name
|
||||
if len(proc.cmdline()) > idx + 1:
|
||||
mount_point = proc.cmdline()[idx + 1]
|
||||
|
||||
# archive or full mount?
|
||||
if parameter[len(repo_url) :].startswith('::'):
|
||||
archive_name = parameter[len(repo_url) + 2 :]
|
||||
mount_points[archive_name] = mount_point
|
||||
break
|
||||
else:
|
||||
# repo mount point
|
||||
repo_mounts.append(mount_point)
|
||||
|
||||
except (psutil.ZombieProcess, psutil.AccessDenied, psutil.NoSuchProcess):
|
||||
# Getting process details may fail (e.g. zombie process on macOS)
|
||||
|
|
|
@ -52,7 +52,7 @@ def __init__(self, parent=None, app=None):
|
|||
"""Init."""
|
||||
super().__init__(parent)
|
||||
self.setupUi(parent)
|
||||
self.mount_points = {} # mount points of archives
|
||||
self.mount_points = {} # mapping of archive name to mount point
|
||||
self.repo_mount_point: Optional[str] = None # mount point of whole repo
|
||||
self.menu = None
|
||||
self.app = app
|
||||
|
@ -565,17 +565,11 @@ def mount_action(self, archive_name=None):
|
|||
The archive to mount or None, by default None
|
||||
"""
|
||||
profile = self.profile()
|
||||
params = BorgMountJob.prepare(profile)
|
||||
params = BorgMountJob.prepare(profile, archive=archive_name)
|
||||
if not params['ok']:
|
||||
self._set_status(params['message'])
|
||||
return
|
||||
|
||||
if archive_name:
|
||||
# mount archive
|
||||
params['cmd'][-1] += f'::{archive_name}'
|
||||
params['current_archive'] = archive_name
|
||||
# else mount complete repo
|
||||
|
||||
def receive():
|
||||
mount_point = dialog.selectedFiles()
|
||||
if mount_point:
|
||||
|
@ -598,13 +592,12 @@ def mount_result(self, result):
|
|||
|
||||
mount_point = result['params']['mount_point']
|
||||
|
||||
if result['params'].get('current_archive'):
|
||||
if result['params'].get('mounted_archive'):
|
||||
# archive was mounted
|
||||
archive_name = result['params']['current_archive']
|
||||
archive_name = result['params']['mounted_archive']
|
||||
self.mount_points[archive_name] = mount_point
|
||||
|
||||
# update column in table
|
||||
archive_name = result['params']['current_archive']
|
||||
row = self.row_of_archive(archive_name)
|
||||
item = QTableWidgetItem(result['cmd'][-1])
|
||||
self.archiveTable.setItem(row, 3, item)
|
||||
|
|
Loading…
Reference in a new issue