191 lines
6.3 KiB
Python
191 lines
6.3 KiB
Python
# SPDX-FileCopyrightText: 2021 Blender Studio Tools Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from typing import Optional, Any, Set, Tuple, List
|
|
import platform
|
|
|
|
import bpy
|
|
from bpy.props import IntProperty, CollectionProperty, BoolProperty, EnumProperty
|
|
from bpy.types import AddonPreferences
|
|
|
|
from .ui.ui_repo_list import draw_checkout, draw_repo_list
|
|
from .repository import SVN_repository
|
|
from .svn_info import get_svn_info
|
|
import json
|
|
from pathlib import Path
|
|
from .threaded.background_process import Processes
|
|
|
|
|
|
class SVN_addon_preferences(AddonPreferences):
|
|
bl_idname = __package__
|
|
|
|
is_svn_installed: BoolProperty(
|
|
name="Is SVN Installed",
|
|
description="Whether the `svn` command works at all in the user's command line. If not, user needs to install SVN",
|
|
default=False
|
|
)
|
|
|
|
repositories: CollectionProperty(type=SVN_repository)
|
|
|
|
def init_repo_list(self):
|
|
# If we have any repository entries, make sure at least one is active.
|
|
self.sync_repo_info_file()
|
|
|
|
if self.active_repo_idx == -1 and len(self.repositories) > 0:
|
|
self.active_repo_idx = 0
|
|
elif self.active_repo_idx > len(self.repositories)-1:
|
|
self.active_repo_idx = 0
|
|
else:
|
|
self.active_repo_idx = self.active_repo_idx
|
|
|
|
def init_repo(self, context, repo_path: Path or str):
|
|
"""Attempt to initialize a repository based on a directory.
|
|
This means executing `svn info` in the repo_path to get the URL and root dir.
|
|
If we already have an SVN_repository instance with that root dir, just return it.
|
|
Otherwise, initialize it by storing its directory, URL, and a display name, and then return it.
|
|
"""
|
|
root_dir, base_url = get_svn_info(repo_path)
|
|
if not root_dir:
|
|
return
|
|
existing_repo = self.repositories.get(root_dir)
|
|
if existing_repo:
|
|
if existing_repo.external_files_active_index > len(existing_repo.external_files):
|
|
existing_repo.external_files_active_index = 0
|
|
existing_repo.log_active_index = len(existing_repo.log)-1
|
|
existing_repo.reload_svn_log(context)
|
|
return existing_repo
|
|
|
|
repo = self.repositories.add()
|
|
repo.initialize(root_dir, base_url)
|
|
self.active_repo_idx = len(self.repositories)-1
|
|
|
|
return repo
|
|
|
|
checkout_mode: BoolProperty(
|
|
name="Checkout In Progress",
|
|
description="Internal flag to indicate that the user is currently trying to create a new checkout",
|
|
default=False
|
|
)
|
|
|
|
def update_active_repo_idx(self, context):
|
|
if len(self.repositories) == 0:
|
|
return
|
|
active_repo = self.active_repo
|
|
|
|
# Authenticate when switching repos.
|
|
if (
|
|
active_repo and
|
|
not active_repo.auth_failed and
|
|
active_repo.is_cred_entered
|
|
):
|
|
Processes.start('Redraw Viewport')
|
|
if active_repo.authenticated:
|
|
Processes.restart('Status')
|
|
else:
|
|
active_repo.authenticate()
|
|
else:
|
|
Processes.kill('Status')
|
|
|
|
active_repo_idx: IntProperty(
|
|
name="SVN Repositories",
|
|
options=set(),
|
|
update=update_active_repo_idx
|
|
)
|
|
|
|
@property
|
|
def active_repo(self) -> Optional[SVN_repository]:
|
|
if not self.is_svn_installed:
|
|
return
|
|
if 0 <= self.active_repo_idx <= len(self.repositories)-1:
|
|
return self.repositories[self.active_repo_idx]
|
|
|
|
debug_mode: BoolProperty(
|
|
name="Debug Mode",
|
|
description="Enable some debug UI",
|
|
default=False
|
|
)
|
|
|
|
@property
|
|
def is_busy(self):
|
|
return Processes.is_running('Commit', 'Update')
|
|
|
|
loading: BoolProperty(
|
|
name="Loading",
|
|
description="Disable the credential update callbacks while loading repo data to avoid infinite loops",
|
|
default=False
|
|
)
|
|
|
|
def save_repo_info_to_file(self):
|
|
saved_props = {'url', 'directory', 'name',
|
|
'username', 'password', 'display_name'}
|
|
repo_data = {}
|
|
for repo in self.repositories:
|
|
directory = repo.get('directory', '')
|
|
|
|
repo_data[directory] = {
|
|
key: value for key, value in repo.items() if key in saved_props}
|
|
|
|
filepath = Path(bpy.utils.user_resource('CONFIG')) / \
|
|
Path("blender_svn.txt")
|
|
with open(filepath, "w") as f:
|
|
json.dump(repo_data, f, indent=4)
|
|
|
|
def load_repo_info_from_file(self):
|
|
self.loading = True
|
|
try:
|
|
filepath = Path(bpy.utils.user_resource(
|
|
'CONFIG')) / Path("blender_svn.txt")
|
|
if not filepath.exists():
|
|
return
|
|
|
|
with open(filepath, "r") as f:
|
|
repo_data = json.load(f)
|
|
|
|
for directory, repo_data in repo_data.items():
|
|
repo = self.repositories.get(directory)
|
|
if not repo:
|
|
repo = self.repositories.add()
|
|
repo.directory = directory
|
|
for key, value in repo_data.items():
|
|
setattr(repo, key, value)
|
|
finally:
|
|
self.loading = False
|
|
|
|
def sync_repo_info_file(self):
|
|
self.load_repo_info_from_file()
|
|
self.save_repo_info_to_file()
|
|
|
|
def draw(self, context):
|
|
if not self.is_svn_installed:
|
|
draw_prefs_no_svn(self, context)
|
|
return
|
|
|
|
if self.checkout_mode:
|
|
draw_checkout(self, context)
|
|
else:
|
|
draw_repo_list(self, context)
|
|
|
|
|
|
def draw_prefs_no_svn(self, context):
|
|
terminal, url = "terminal", "https://subversion.apache.org/packages.html"
|
|
system = platform.system()
|
|
if system == "Windows":
|
|
terminal = "command line (cmd.exe)"
|
|
url = "https://subversion.apache.org/packages.html#windows"
|
|
elif system == "Darwin":
|
|
terminal = "Mac terminal"
|
|
url = "https://subversion.apache.org/packages.html#osx"
|
|
|
|
layout = self.layout
|
|
col = layout.column()
|
|
col.alert=True
|
|
col.label(text="Please ensure that Subversion (aka. SVN) is installed on your system.")
|
|
col.label(text=f"Typing `svn` into the {terminal} should yield a result.")
|
|
layout.operator("wm.url_open", icon='URL', text='Open Subversion Distribution Page').url=url
|
|
|
|
|
|
registry = [
|
|
SVN_addon_preferences
|
|
]
|