SVN: Checkout, Multi-Repo, Optimizations & Clean-up #104

Merged
Demeter Dzadik merged 12 commits from Mets/blender-studio-pipeline:SVN-improvements into main 2023-07-10 16:49:03 +02:00
5 changed files with 56 additions and 40 deletions
Showing only changes of commit aea472eee9 - Show all commits

View File

@ -18,6 +18,11 @@ from ..util import get_addon_prefs, redraw_viewport
# TODO: Add an operator to revert all local changes to the working copy.
class SVN_Operator:
@staticmethod
def update_file_list(context):
repo = context.scene.svn.get_repo(context)
repo.update_file_filter(context)
def execute_svn_command(self, context, command: List[str], use_cred=False) -> str:
# Since a status update might already be being requested when an SVN operator is run,
# we want to ignore the first update after any SVN operator.
@ -51,6 +56,7 @@ class SVN_Operator_Single_File(SVN_Operator):
# file.status_prediction_type = "SKIP_ONCE"
redraw_viewport()
self.update_file_list(context)
return ret
def _execute(self, context: Context) -> Set[str]:
@ -227,13 +233,14 @@ class SVN_OT_download_repo_revision(SVN_Operator, Operator):
# NOTE: This can take a long time, but providing a progress bar is
# fundamentally impossible because SVN itself doesn't provide the command
# line with any progress info.
# TODO: Doing it in the background may be an option, just a hassle.
# TODO: Should run in the background like regular `svn up`.
output = self.execute_svn_command(
context,
["svn", "up", f"-r{self.revision}", "--accept", "postpone"],
use_cred=True
)
self.report({"INFO"}, output.split("\n")[-2])
self.update_file_list(context)
return {"FINISHED"}
def set_predicted_file_status(self, repo, file_entry: "SVN_file"):

View File

@ -123,6 +123,16 @@ class SVN_file(PropertyGroup):
return 'QUESTION'
@property
def has_default_status(self):
return self.status == 'normal' and self.repos_status == 'none' and self.status_prediction_type == 'NONE'
show_in_filelist: BoolProperty(
name="Show In File List",
description="Flag indicating whether this file should be drawn in the file list. This flag is updated for every file whenever the file search string is modified. If we did this filtering during drawing time, it is painfully slow",
default=False
)
class SVN_log(PropertyGroup):
"""Property Group that can represent an SVN log entry."""
@ -251,6 +261,8 @@ class SVN_repository(PropertyGroup):
self.auth_failed = False
if self.exists and self.is_cred_entered:
Processes.start('Authenticate')
# Trigger the file list filtering.
self.file_search_filter = self.file_search_filter
username: StringProperty(
name="Username",
@ -467,18 +479,11 @@ class SVN_repository(PropertyGroup):
return self.get_file_by_absolute_path(bpy.data.filepath)
### File List UIList filter properties ###
# These are normally stored on the UIList, but then they cannot be accessed
# from anywhere else, since template_list() does not return the UIList instance.
# Filtering properties are normally stored on the UIList,
# but then they cannot be accessed from anywhere else,
# since template_list() does not return the UIList instance.
# We need to be able to access them outside of drawing code, to be able to
# know which entries are visible and ensure that a filtered out entry can never
# be the active one.
def get_visible_indicies(self, context) -> List[int]:
flt_flags, _flt_neworder = bpy.types.SVN_UL_file_list.cls_filter_items(
context, self, 'external_files')
visible_indicies = [i for i, flag in enumerate(flt_flags) if flag != 0]
return visible_indicies
# ensure that a filtered out entry can never be the active one.
def force_good_active_index(self, context) -> bool:
"""
@ -486,14 +491,34 @@ class SVN_repository(PropertyGroup):
If the active element is being filtered out, set the active element to
something that is visible.
"""
visible_indicies = self.get_visible_indicies(context)
if len(visible_indicies) == 0:
self.external_files_active_index = 0
elif self.external_files_active_index not in visible_indicies:
self.external_files_active_index = visible_indicies[0]
if not self.active_file.show_in_filelist:
for i, file in enumerate(self.external_files):
if file.show_in_filelist:
self.external_files_active_index = i
return
def update_file_filter(self, context):
"""Should run when any of the SVN file list search filters are changed."""
UI_LIST = bpy.types.UI_UL_list
if self.file_search_filter:
filter_list = UI_LIST.filter_items_by_name(
self.file_search_filter,
1,
self.external_files,
"name",
reverse=False
)
filter_list = [bool(val) for val in filter_list]
self.external_files.foreach_set('show_in_filelist', filter_list)
else:
for file in self.external_files:
if file == self.current_blend_file:
file.show_in_filelist = True
continue
file.show_in_filelist = not file.has_default_status
self.force_good_active_index(context)
file_search_filter: StringProperty(

View File

@ -273,6 +273,7 @@ def update_file_list(context, file_statuses: Dict[str, Tuple[str, str, int]]):
if file_entry.svn_path not in svn_paths:
repo.remove_file_entry(file_entry)
repo.update_file_filter(context)
repo.force_good_active_index(context)

View File

@ -121,9 +121,9 @@ class SVN_UL_file_list(UIList):
properties to the addon preferences) we can find a visible entry
from other UI code, allowing us to avoid situations where the active
element becomes hidden."""
flt_flags = []
flt_neworder = []
list_items = getattr(data, propname)
flt_flags = [file.show_in_filelist * cls.UILST_FLT_ITEM for file in list_items]
helper_funcs = bpy.types.UI_UL_list
@ -134,25 +134,6 @@ class SVN_UL_file_list(UIList):
if not repo:
return flt_flags, flt_neworder
def has_default_status(file):
return file.status == 'normal' and file.repos_status == 'none' and file.status_prediction_type == 'NONE'
if repo.file_search_filter:
flt_flags = helper_funcs.filter_items_by_name(repo.file_search_filter, cls.UILST_FLT_ITEM, list_items, "name",
reverse=False)
else:
# Start with all files visible.
flt_flags = [cls.UILST_FLT_ITEM] * len(list_items)
for i, item in enumerate(list_items):
if item == repo.current_blend_file:
# ALWAYS display the current .blend file.
continue
if has_default_status(item):
# Filter out files that have default statuses.
flt_flags[i] = 0
return flt_flags, flt_neworder
def filter_items(self, context, data, propname):

View File

@ -99,13 +99,15 @@ def is_log_useful(context):
repo = context.scene.svn.get_repo(context)
if len(repo.log) == 0:
return False
any_visible = repo.get_visible_indicies(context)
if not any_visible:
return False
active_file = repo.active_file
if active_file.status in ['unversioned', 'added']:
return False
if repo.file_search_filter:
any_visible = any([file.show_in_filelist for file in repo.external_files])
if not any_visible:
return False
return True