1
0
Fork 0
mirror of https://github.com/borgbase/vorta synced 2024-12-21 23:33:13 +00:00

Assign names to repos. By @diivi (#1665)

This commit is contained in:
Divyansh Singh 2023-06-25 01:27:46 +05:30 committed by GitHub
parent f76195e47d
commit 92608f9eaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 332 additions and 278 deletions

View file

@ -1,278 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddRepository</class>
<widget class="QDialog" name="AddRepository">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>466</width>
<height>274</height>
</rect>
</property>
<property name="modal">
<class>AddRepository</class>
<widget class="QDialog" name="AddRepository">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>583</width>
<height>338</height>
</rect>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="errorText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="errorText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabWidgetPage1">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QFormLayout" name="repoDataFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="title">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Initialize New Backup Repository</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="repoLabel">
<property name="text">
<string>Repository URL:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="repoURL">
<property name="placeholderText">
<string>ssh://abc123@abc123.repo.borgbase.com/./repo</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="chooseLocalFolderButton">
<property name="toolTip">
<string>Choose a local folder</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/folder-open.svg</normaloff>:/icons/folder-open.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="useRemoteRepoButton">
<property name="toolTip">
<string>Choose a remote repository</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/globe.svg</normaloff>:/icons/globe.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Repository Name:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="repoName">
<property name="placeholderText">
<string>Macbook Pro Office (optional)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string />
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabWidgetPage1">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QFormLayout" name="repoDataFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="title">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Initialize New Backup Repository</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="repoLabel">
<property name="text">
<string>Repository URL:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="repoURL">
<property name="placeholderText">
<string>ssh://abc123@abc123.repo.borgbase.com/./repo</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="chooseLocalFolderButton">
<property name="toolTip">
<string>Choose a local folder</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/folder-open.svg</normaloff>:/icons/folder-open.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="useRemoteRepoButton">
<property name="toolTip">
<string>Choose a remote repository</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/globe.svg</normaloff>:/icons/globe.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Borg passphrase:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="confirmLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="confirmLabel">
<property name="text">
<string>Confirm passphrase:</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWidgetPage2">
<attribute name="title">
<string>Advanced</string>
</attribute>
<layout class="QFormLayout" name="advancedFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="sshComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="encryptionLabel">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="encryptionComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Extra Borg Arguments:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="extraBorgArgumentsLineEdit" />
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Borg passphrase:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="confirmLabel">
<property name="text">
<string>Confirm passphrase:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="confirmLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWidgetPage2">
<attribute name="title">
<string>Advanced</string>
</attribute>
<layout class="QFormLayout" name="advancedFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="sshComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<resources />
<connections />
</item>
<item row="1" column="0">
<widget class="QLabel" name="encryptionLabel">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="encryptionComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Extra Borg Arguments:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="extraBorgArgumentsLineEdit"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" fill="#000000"
viewBox="0 0 1536 1536" style="enable-background:new 0 0 1536 1536;" xml:space="preserve">
<path d="M483.4,1088l65.1-120.3C451.6,896,394,780.8,394,658.8c0-67.4,17.5-134,50.9-192C314.7,535,206.2,642.6,126.9,768
C213.7,905.4,336.5,1020.6,483.4,1088z M808.1,440.3c0-22.2-18.4-41-40.1-41c-139.4,0-253.8,116.9-253.8,259.4

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" fill="#000000"
viewBox="0 0 1536 1536" style="enable-background:new 0 0 1536 1536;" xml:space="preserve">
<path d="M1404.2,768c-78.7-121.8-186.4-226.2-315.6-292.4c33.1,56.3,50.5,120.9,50.5,186.4c0,204.6-166.5,371.1-371.1,371.1
S396.9,866.6,396.9,662c0-65.4,17.4-130.1,50.5-186.4C318.2,541.8,210.5,646.2,131.8,768c141.7,218.7,370.3,371.1,636.2,371.1

Before

Width:  |  Height:  |  Size: 972 B

After

Width:  |  Height:  |  Size: 987 B

View file

@ -27,7 +27,7 @@
db_lock = Lock()
logger = logging.getLogger(__name__)
FakeRepo = namedtuple('Repo', ['url', 'id', 'extra_borg_arguments', 'encryption'])
FakeRepo = namedtuple('Repo', ['url', 'name', 'id', 'extra_borg_arguments', 'encryption'])
FakeProfile = namedtuple('FakeProfile', ['id', 'repo', 'name', 'ssh_key'])
"""
@ -190,6 +190,7 @@ def prepare(cls, profile):
ret['ssh_key'] = profile.ssh_key
ret['repo_id'] = profile.repo.id
ret['repo_url'] = profile.repo.url
ret['repo_name'] = profile.repo.name
ret['extra_borg_arguments'] = profile.repo.extra_borg_arguments
ret['profile_name'] = profile.name
ret['profile_id'] = profile.id

View file

@ -18,7 +18,7 @@ def prepare(cls, params):
# Build fake profile because we don't have it in the DB yet. Assume unencrypted.
profile = FakeProfile(
999,
FakeRepo(params['repo_url'], 999, params['extra_borg_arguments'], 'none'),
FakeRepo(params['repo_url'], params['repo_name'], 999, params['extra_borg_arguments'], 'none'),
'New Repo',
params['ssh_key'],
)
@ -47,6 +47,7 @@ def prepare(cls, params):
ret['message'] = trans_late('messages', 'Please unlock your password manager.')
return ret
ret['repo_name'] = params['repo_name']
ret['ok'] = True
ret['cmd'] = cmd
@ -54,7 +55,9 @@ def prepare(cls, params):
def process_result(self, result):
if result['returncode'] == 0:
new_repo, _ = RepoModel.get_or_create(url=result['cmd'][-1])
new_repo, _ = RepoModel.get_or_create(
url=result['cmd'][-1], defaults={'name': result['params']['repo_name']}
)
if 'cache' in result['data']:
stats = result['data']['cache']['stats']
new_repo.total_size = stats['total_size']
@ -64,7 +67,6 @@ def process_result(self, result):
new_repo.encryption = result['data']['encryption']['mode']
if new_repo.encryption != 'none':
self.keyring.set_password("vorta-repo", new_repo.url, result['params']['password'])
new_repo.extra_borg_arguments = result['params']['extra_borg_arguments']
new_repo.save()

View file

@ -16,6 +16,7 @@ def prepare(cls, params):
999,
FakeRepo(
params['repo_url'],
params['repo_name'],
999,
params['extra_borg_arguments'],
params['encryption'],
@ -61,6 +62,7 @@ def process_result(self, result):
defaults={
'encryption': result['params']['encryption'],
'extra_borg_arguments': result['params']['extra_borg_arguments'],
'name': result['params']['repo_name'],
},
)
if new_repo.encryption != 'none':

View file

@ -21,7 +21,7 @@
)
from .settings import get_misc_settings
SCHEMA_VERSION = 21
SCHEMA_VERSION = 22
@signals.post_save(sender=SettingsModel)

View file

@ -239,6 +239,17 @@ def run_migrations(current_schema, db_connection):
),
)
if current_schema.version < 22:
_apply_schema_update(
current_schema,
22,
migrator.add_column(
RepoModel._meta.table_name,
'name',
pw.CharField(default=''),
),
)
def _apply_schema_update(current_schema, version_after, *operations):
with DB.atomic():

View file

@ -39,6 +39,7 @@ class RepoModel(BaseModel):
"""A single remote repo with unique URL."""
url = pw.CharField(unique=True)
name = pw.CharField(default='')
added_at = pw.DateTimeField(default=datetime.now)
encryption = pw.CharField(null=True)
unique_size = pw.IntegerField(null=True)

View file

@ -265,7 +265,12 @@ def populate_from_profile(self):
if repo_mount_points:
self.repo_mount_point = repo_mount_points[0]
self.toolBox.setItemText(0, self.tr('Archives for %s') % profile.repo.url)
if profile.repo.name:
repo_name = f"{profile.repo.name} ({profile.repo.url})"
else:
repo_name = profile.repo.url
self.toolBox.setItemText(0, self.tr('Archives for {}').format(repo_name))
archives = [s for s in profile.repo.archives.select().order_by(ArchiveModel.time.desc())]
# if no archive's name can be found in self.mount_points, then hide the mount point column

View file

@ -77,6 +77,7 @@ def values(self):
out = dict(
ssh_key=self.sshComboBox.currentData(),
repo_url=self.repoURL.text(),
repo_name=self.repoName.text(),
password=self.passwordLineEdit.text(),
extra_borg_arguments=self.extraBorgArgumentsLineEdit.text(),
)
@ -94,6 +95,7 @@ def receive():
folder = dialog.selectedFiles()
if folder:
self.repoURL.setText(folder[0])
self.repoName.setText(folder[0].split('/')[-1])
self.repoURL.setEnabled(False)
self.sshComboBox.setEnabled(False)
self.repoLabel.setText(self.tr('Repository Path:'))
@ -126,6 +128,7 @@ def set_visibility(self, visible):
def use_remote_repo_action(self):
self.repoURL.setText('')
self.repoURL.setEnabled(True)
self.repoName.setText('')
self.sshComboBox.setEnabled(True)
self.extraBorgArgumentsLineEdit.setText('')
self.repoLabel.setText(self.tr('Repository URL:'))
@ -199,6 +202,10 @@ def validate(self):
self._set_status(self.tr('Please enter a valid repo URL or select a local path.'))
return False
if len(self.values['repo_name']) > 64:
self._set_status(self.tr('Repository name must be less than 64 characters.'))
return False
if RepoModel.get_or_none(RepoModel.url == self.values['repo_url']) is not None:
self._set_status(self.tr('This repo has already been added.'))
return False

View file

@ -79,8 +79,10 @@ def set_icons(self):
def set_repos(self):
self.repoSelector.clear()
self.repoSelector.addItem(self.tr('No repository selected'), None)
# set tooltip = url for each item in the repoSelector
for repo in RepoModel.select():
self.repoSelector.addItem(repo.url, repo.id)
self.repoSelector.addItem(f"{repo.name + ' - ' if repo.name else ''}{repo.url}", repo.id)
self.repoSelector.setItemData(self.repoSelector.count() - 1, repo.url, QtCore.Qt.ItemDataRole.ToolTipRole)
def populate_from_profile(self):
try:

View file

@ -85,8 +85,10 @@ def test_repo_add_success(qapp, qtbot, mocker, borg_json_output):
main.repoTab.new_repo() # couldn't click menu
add_repo_window = main.repoTab._window
test_repo_url = f'vorta-test-repo.{uuid.uuid4()}.com:repo' # Random repo URL to avoid macOS keychain
test_repo_name = 'Test Repo'
qtbot.keyClicks(add_repo_window.repoURL, test_repo_url)
qtbot.keyClicks(add_repo_window.repoName, test_repo_name)
qtbot.keyClicks(add_repo_window.passwordLineEdit, LONG_PASSWORD)
qtbot.keyClicks(add_repo_window.confirmLineEdit, LONG_PASSWORD)
@ -103,7 +105,7 @@ def test_repo_add_success(qapp, qtbot, mocker, borg_json_output):
keyring = VortaKeyring.get_keyring()
assert keyring.get_password("vorta-repo", RepoModel.get(id=2).url) == LONG_PASSWORD
assert main.repoTab.repoSelector.currentText() == test_repo_url
assert main.repoTab.repoSelector.currentText() == f"{test_repo_name} - {test_repo_url}"
def test_ssh_dialog(qapp, qtbot, tmpdir):