feat: update addon updater to support installation from branches (develop and master)
This commit is contained in:
@ -23,7 +23,11 @@ https://github.com/CGCookie/blender-addon-updater
|
||||
|
||||
"""
|
||||
|
||||
__version__ = "1.0.8"
|
||||
|
||||
import errno
|
||||
import traceback
|
||||
import platform
|
||||
import ssl
|
||||
import urllib.request
|
||||
import urllib
|
||||
@ -98,6 +102,7 @@ class Singleton_updater(object):
|
||||
|
||||
# runtime variables, initial conditions
|
||||
self._verbose = False
|
||||
self._use_print_traces = True
|
||||
self._fake_install = False
|
||||
self._async_checking = False # only true when async daemon started
|
||||
self._update_ready = None
|
||||
@ -133,6 +138,13 @@ class Singleton_updater(object):
|
||||
self._select_link = select_link_function
|
||||
|
||||
|
||||
# called from except blocks, to print the exception details,
|
||||
# according to the use_print_traces option
|
||||
def print_trace():
|
||||
if self._use_print_traces:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Getters and setters
|
||||
# -------------------------------------------------------------------------
|
||||
@ -166,7 +178,7 @@ class Singleton_updater(object):
|
||||
try:
|
||||
self._auto_reload_post_update = bool(value)
|
||||
except:
|
||||
raise ValueError("Must be a boolean value")
|
||||
raise ValueError("auto_reload_post_update must be a boolean value")
|
||||
|
||||
@property
|
||||
def backup_current(self):
|
||||
@ -351,7 +363,7 @@ class Singleton_updater(object):
|
||||
try:
|
||||
self._repo = str(value)
|
||||
except:
|
||||
raise ValueError("User must be a string")
|
||||
raise ValueError("repo must be a string value")
|
||||
|
||||
@property
|
||||
def select_link(self):
|
||||
@ -377,6 +389,7 @@ class Singleton_updater(object):
|
||||
os.makedirs(value)
|
||||
except:
|
||||
if self._verbose: print("Error trying to staging path")
|
||||
self.print_trace()
|
||||
return
|
||||
self._updater_path = value
|
||||
|
||||
@ -446,6 +459,16 @@ class Singleton_updater(object):
|
||||
except:
|
||||
raise ValueError("Verbose must be a boolean value")
|
||||
|
||||
@property
|
||||
def use_print_traces(self):
|
||||
return self._use_print_traces
|
||||
@use_print_traces.setter
|
||||
def use_print_traces(self, value):
|
||||
try:
|
||||
self._use_print_traces = bool(value)
|
||||
except:
|
||||
raise ValueError("use_print_traces must be a boolean value")
|
||||
|
||||
@property
|
||||
def version_max_update(self):
|
||||
return self._version_max_update
|
||||
@ -637,6 +660,9 @@ class Singleton_updater(object):
|
||||
else:
|
||||
if self._verbose: print("Tokens not setup for engine yet")
|
||||
|
||||
# Always set user agent
|
||||
request.add_header('User-Agent', "Python/"+str(platform.python_version()))
|
||||
|
||||
# run the request
|
||||
try:
|
||||
if context:
|
||||
@ -652,6 +678,7 @@ class Singleton_updater(object):
|
||||
self._error = "HTTP error"
|
||||
self._error_msg = str(e.code)
|
||||
print(self._error, self._error_msg)
|
||||
self.print_trace()
|
||||
self._update_ready = None
|
||||
except urllib.error.URLError as e:
|
||||
reason = str(e.reason)
|
||||
@ -663,6 +690,7 @@ class Singleton_updater(object):
|
||||
self._error = "URL error, check internet connection"
|
||||
self._error_msg = reason
|
||||
print(self._error, self._error_msg)
|
||||
self.print_trace()
|
||||
self._update_ready = None
|
||||
return None
|
||||
else:
|
||||
@ -684,6 +712,7 @@ class Singleton_updater(object):
|
||||
self._error_msg = str(e.reason)
|
||||
self._update_ready = None
|
||||
print(self._error, self._error_msg)
|
||||
self.print_trace()
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
@ -700,15 +729,17 @@ class Singleton_updater(object):
|
||||
if self._verbose: print("Preparing staging folder for download:\n",local)
|
||||
if os.path.isdir(local) == True:
|
||||
try:
|
||||
shutil.rmtree(local)
|
||||
shutil.rmtree(local, ignore_errors=True)
|
||||
os.makedirs(local)
|
||||
except:
|
||||
error = "failed to remove existing staging directory"
|
||||
self.print_trace()
|
||||
else:
|
||||
try:
|
||||
os.makedirs(local)
|
||||
except:
|
||||
error = "failed to create staging directory"
|
||||
self.print_trace()
|
||||
|
||||
if error != None:
|
||||
if self._verbose: print("Error: Aborting update, "+error)
|
||||
@ -722,20 +753,23 @@ class Singleton_updater(object):
|
||||
|
||||
self._source_zip = os.path.join(local,"source.zip")
|
||||
|
||||
if self._verbose: print(f"Starting download update zip to {self._source_zip}")
|
||||
if self._verbose: print("Starting download update zip")
|
||||
try:
|
||||
import urllib3
|
||||
http = urllib3.PoolManager()
|
||||
r = http.request('GET', url, preload_content=False)
|
||||
chunk_size = 1024*8
|
||||
with open(self._source_zip, 'wb') as out:
|
||||
while True:
|
||||
data = r.read(chunk_size)
|
||||
if not data:
|
||||
break
|
||||
out.write(data)
|
||||
request = urllib.request.Request(url)
|
||||
context = ssl._create_unverified_context()
|
||||
|
||||
r.release_conn()
|
||||
# setup private token if appropriate
|
||||
if self._engine.token != None:
|
||||
if self._engine.name == "gitlab":
|
||||
request.add_header('PRIVATE-TOKEN',self._engine.token)
|
||||
else:
|
||||
if self._verbose: print("Tokens not setup for selected engine yet")
|
||||
|
||||
# Always set user agent
|
||||
request.add_header('User-Agent', "Python/"+str(platform.python_version()))
|
||||
|
||||
self.urlretrieve(urllib.request.urlopen(request,context=context), self._source_zip)
|
||||
# add additional checks on file size being non-zero
|
||||
if self._verbose: print("Successfully downloaded update zip")
|
||||
return True
|
||||
except Exception as e:
|
||||
@ -744,6 +778,7 @@ class Singleton_updater(object):
|
||||
if self._verbose:
|
||||
print("Error retrieving download, bad link?")
|
||||
print("Error: {}".format(e))
|
||||
self.print_trace()
|
||||
return False
|
||||
|
||||
|
||||
@ -758,16 +793,18 @@ class Singleton_updater(object):
|
||||
|
||||
if os.path.isdir(local):
|
||||
try:
|
||||
shutil.rmtree(local)
|
||||
shutil.rmtree(local, ignore_errors=True)
|
||||
except:
|
||||
if self._verbose:print("Failed to removed previous backup folder, contininuing")
|
||||
self.print_trace()
|
||||
|
||||
# remove the temp folder; shouldn't exist but could if previously interrupted
|
||||
if os.path.isdir(tempdest):
|
||||
try:
|
||||
shutil.rmtree(tempdest)
|
||||
shutil.rmtree(tempdest, ignore_errors=True)
|
||||
except:
|
||||
if self._verbose:print("Failed to remove existing temp folder, contininuing")
|
||||
self.print_trace()
|
||||
# make the full addon copy, which temporarily places outside the addon folder
|
||||
if self._backup_ignore_patterns != None:
|
||||
shutil.copytree(
|
||||
@ -795,7 +832,7 @@ class Singleton_updater(object):
|
||||
|
||||
# make the copy
|
||||
shutil.move(backuploc,tempdest)
|
||||
shutil.rmtree(self._addon_root)
|
||||
shutil.rmtree(self._addon_root, ignore_errors=True)
|
||||
os.rename(tempdest,self._addon_root)
|
||||
|
||||
self._json["backup_date"] = ""
|
||||
@ -816,7 +853,7 @@ class Singleton_updater(object):
|
||||
# clear the existing source folder in case previous files remain
|
||||
outdir = os.path.join(self._updater_path, "source")
|
||||
try:
|
||||
shutil.rmtree(outdir)
|
||||
shutil.rmtree(outdir, ignore_errors=True)
|
||||
if self._verbose:
|
||||
print("Source folder cleared")
|
||||
except:
|
||||
@ -829,6 +866,7 @@ class Singleton_updater(object):
|
||||
except Exception as err:
|
||||
print("Error occurred while making extract dir:")
|
||||
print(str(err))
|
||||
self.print_trace()
|
||||
self._error = "Install failed"
|
||||
self._error_msg = "Failed to make extract directory"
|
||||
return -1
|
||||
@ -870,6 +908,7 @@ class Singleton_updater(object):
|
||||
if exc.errno != errno.EEXIST:
|
||||
self._error = "Install failed"
|
||||
self._error_msg = "Could not create folder from zip"
|
||||
self.print_trace()
|
||||
return -1
|
||||
else:
|
||||
with open(os.path.join(outdir, subpath), "wb") as outfile:
|
||||
@ -963,12 +1002,13 @@ class Singleton_updater(object):
|
||||
print("Clean removing file {}".format(os.path.join(base,f)))
|
||||
for f in folders:
|
||||
if os.path.join(base,f)==self._updater_path: continue
|
||||
shutil.rmtree(os.path.join(base,f))
|
||||
shutil.rmtree(os.path.join(base,f), ignore_errors=True)
|
||||
print("Clean removing folder and contents {}".format(os.path.join(base,f)))
|
||||
|
||||
except Exception as err:
|
||||
error = "failed to create clean existing addon folder"
|
||||
print(error, str(err))
|
||||
self.print_trace()
|
||||
|
||||
# Walk through the base addon folder for rules on pre-removing
|
||||
# but avoid removing/altering backup and updater file
|
||||
@ -984,6 +1024,7 @@ class Singleton_updater(object):
|
||||
if self._verbose: print("Pre-removed file "+file)
|
||||
except OSError:
|
||||
print("Failed to pre-remove "+file)
|
||||
self.print_trace()
|
||||
|
||||
# Walk through the temp addon sub folder for replacements
|
||||
# this implements the overwrite rules, which apply after
|
||||
@ -1007,7 +1048,7 @@ class Singleton_updater(object):
|
||||
# otherwise, check each file to see if matches an overwrite pattern
|
||||
replaced=False
|
||||
for ptrn in self._overwrite_patterns:
|
||||
if fnmatch.filter([destFile],ptrn):
|
||||
if fnmatch.filter([file],ptrn):
|
||||
replaced=True
|
||||
break
|
||||
if replaced:
|
||||
@ -1023,10 +1064,11 @@ class Singleton_updater(object):
|
||||
|
||||
# now remove the temp staging folder and downloaded zip
|
||||
try:
|
||||
shutil.rmtree(staging_path)
|
||||
shutil.rmtree(staging_path, ignore_errors=True)
|
||||
except:
|
||||
error = "Error: Failed to remove existing staging directory, consider manually removing "+staging_path
|
||||
if self._verbose: print(error)
|
||||
self.print_trace()
|
||||
|
||||
|
||||
def reload_addon(self):
|
||||
@ -1042,9 +1084,16 @@ class Singleton_updater(object):
|
||||
|
||||
# not allowed in restricted context, such as register module
|
||||
# toggle to refresh
|
||||
if "addon_disable" in dir(bpy.ops.wm): # 2.7
|
||||
bpy.ops.wm.addon_disable(module=self._addon_package)
|
||||
bpy.ops.wm.addon_refresh()
|
||||
bpy.ops.wm.addon_enable(module=self._addon_package)
|
||||
print("2.7 reload complete")
|
||||
else: # 2.8
|
||||
bpy.ops.preferences.addon_disable(module=self._addon_package)
|
||||
bpy.ops.preferences.addon_refresh()
|
||||
bpy.ops.preferences.addon_enable(module=self._addon_package)
|
||||
print("2.8 reload complete")
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
@ -1376,7 +1425,7 @@ class Singleton_updater(object):
|
||||
|
||||
if "last_check" not in self._json or self._json["last_check"] == "":
|
||||
return True
|
||||
else:
|
||||
|
||||
now = datetime.now()
|
||||
last_check = datetime.strptime(self._json["last_check"],
|
||||
"%Y-%m-%d %H:%M:%S.%f")
|
||||
@ -1392,7 +1441,7 @@ class Singleton_updater(object):
|
||||
if self._verbose:
|
||||
print("{} Updater: Time to check for updates!".format(self._addon))
|
||||
return True
|
||||
else:
|
||||
|
||||
if self._verbose:
|
||||
print("{} Updater: Determined it's not yet time to check for updates".format(self._addon))
|
||||
return False
|
||||
@ -1414,6 +1463,7 @@ class Singleton_updater(object):
|
||||
except Exception as err:
|
||||
print("Other OS error occurred while trying to rename old JSON")
|
||||
print(err)
|
||||
self.print_trace()
|
||||
return json_path
|
||||
|
||||
def set_updater_json(self):
|
||||
@ -1514,6 +1564,7 @@ class Singleton_updater(object):
|
||||
except Exception as exception:
|
||||
print("Checking for update error:")
|
||||
print(exception)
|
||||
self.print_trace()
|
||||
if not self._error:
|
||||
self._update_ready = False
|
||||
self._update_version = None
|
||||
@ -1625,9 +1676,6 @@ class GitlabEngine(object):
|
||||
return "{}{}{}".format(self.api_url,"/api/v4/projects/",updater.repo)
|
||||
|
||||
def form_tags_url(self, updater):
|
||||
if updater.use_releases:
|
||||
return "{}{}".format(self.form_repo_url(updater),"/releases")
|
||||
else:
|
||||
return "{}{}".format(self.form_repo_url(updater),"/repository/tags")
|
||||
|
||||
def form_branch_list_url(self, updater):
|
||||
@ -1656,14 +1704,9 @@ class GitlabEngine(object):
|
||||
def parse_tags(self, response, updater):
|
||||
if response == None:
|
||||
return []
|
||||
# Return asset links from release
|
||||
if updater.use_releases:
|
||||
return [{"name": release["name"], "zipball_url": release["assets"]["links"][0]["url"]} for release in response]
|
||||
else:
|
||||
return [{"name": tag["name"], "zipball_url": self.get_zip_url(tag["commit"]["id"], updater)} for tag in response]
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The module-shared class instance,
|
||||
# should be what's imported to other files
|
||||
|
@ -16,7 +16,13 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
"""Blender UI integrations for the addon updater.
|
||||
|
||||
Implements draw calls, popups, and operators that use the addon_updater.
|
||||
"""
|
||||
|
||||
import os
|
||||
import traceback
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
@ -28,16 +34,16 @@ try:
|
||||
except Exception as e:
|
||||
print("ERROR INITIALIZING UPDATER")
|
||||
print(str(e))
|
||||
|
||||
traceback.print_exc()
|
||||
class Singleton_updater_none(object):
|
||||
def __init__(self):
|
||||
self.addon = None
|
||||
self.verbose = False
|
||||
self.use_print_traces = True
|
||||
self.invalidupdater = True # used to distinguish bad install
|
||||
self.error = None
|
||||
self.error_msg = None
|
||||
self.async_checking = None
|
||||
|
||||
def clear_state(self):
|
||||
self.addon = None
|
||||
self.verbose = False
|
||||
@ -45,7 +51,6 @@ except Exception as e:
|
||||
self.error = None
|
||||
self.error_msg = None
|
||||
self.async_checking = None
|
||||
|
||||
def run_update(self): pass
|
||||
def check_for_update(self): pass
|
||||
updater = Singleton_updater_none()
|
||||
@ -150,8 +155,7 @@ class addon_updater_install_popup(bpy.types.Operator):
|
||||
col.scale_y = 0.7
|
||||
col.label(text="Update {} ready!".format(str(updater.update_version)),
|
||||
icon="LOOP_FORWARDS")
|
||||
col.label(
|
||||
text="Choose 'Update Now' & press OK to install, ", icon="BLANK1")
|
||||
col.label(text="Choose 'Update Now' & press OK to install, ",icon="BLANK1")
|
||||
col.label(text="or click outside window to defer",icon="BLANK1")
|
||||
row = col.row()
|
||||
row.prop(self,"ignore_enum",expand=True)
|
||||
@ -285,13 +289,12 @@ class addon_updater_update_now(bpy.types.Operator):
|
||||
|
||||
# should return 0, if not something happened
|
||||
if updater.verbose:
|
||||
if res == 0:
|
||||
print("Updater returned successful")
|
||||
else:
|
||||
print("Updater returned "+str(res)+", error occurred")
|
||||
if res==0: print("Updater returned successful")
|
||||
else: print("Updater returned "+str(res)+", error occurred")
|
||||
except Exception as e:
|
||||
updater._error = "Error trying to run update"
|
||||
updater._error_msg = str(e)
|
||||
updater.print_trace()
|
||||
atr = addon_updater_install_manually.bl_idname.split(".")
|
||||
getattr(getattr(bpy.ops, atr[0]),atr[1])('INVOKE_DEFAULT')
|
||||
elif updater.update_ready == None:
|
||||
@ -302,9 +305,10 @@ class addon_updater_update_now(bpy.types.Operator):
|
||||
|
||||
elif updater.update_ready == False:
|
||||
self.report({'INFO'}, "Nothing to update")
|
||||
return {'CANCELLED'}
|
||||
else:
|
||||
self.report(
|
||||
{'ERROR'}, "Encountered problem while trying to update")
|
||||
self.report({'ERROR'}, "Encountered problem while trying to update")
|
||||
return {'CANCELLED'}
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@ -346,8 +350,7 @@ class addon_updater_update_target(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if updater.invalidupdater == True:
|
||||
return False
|
||||
if updater.invalidupdater == True: return False
|
||||
return updater.update_ready != None and len(updater.tags)>0
|
||||
|
||||
def invoke(self, context, event):
|
||||
@ -364,6 +367,7 @@ class addon_updater_update_target(bpy.types.Operator):
|
||||
subcol = split.column()
|
||||
subcol.prop(self, "target", text="")
|
||||
|
||||
|
||||
def execute(self,context):
|
||||
|
||||
# in case of error importing updater
|
||||
@ -415,10 +419,8 @@ class addon_updater_install_manually(bpy.types.Operator):
|
||||
if self.error!="":
|
||||
col = layout.column()
|
||||
col.scale_y = 0.7
|
||||
col.label(
|
||||
text="There was an issue trying to auto-install", icon="ERROR")
|
||||
col.label(
|
||||
text="Press the download button below and install", icon="BLANK1")
|
||||
col.label(text="There was an issue trying to auto-install",icon="ERROR")
|
||||
col.label(text="Press the download button below and install",icon="BLANK1")
|
||||
col.label(text="the zip file like a normal addon.",icon="BLANK1")
|
||||
else:
|
||||
col = layout.column()
|
||||
@ -449,7 +451,6 @@ class addon_updater_install_manually(bpy.types.Operator):
|
||||
row.label(text="See source website to download the update")
|
||||
|
||||
def execute(self,context):
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@ -497,16 +498,23 @@ class addon_updater_updated_successful(bpy.types.Operator):
|
||||
# tell user to restart blender
|
||||
if "just_restored" in saved and saved["just_restored"] == True:
|
||||
col = layout.column()
|
||||
col.scale_y = 0.7
|
||||
col.label(text="Addon restored", icon="RECOVER_LAST")
|
||||
col.label(text="Restart blender to reload.", icon="BLANK1")
|
||||
alert_row = col.row()
|
||||
alert_row.alert = True
|
||||
alert_row.operator(
|
||||
"wm.quit_blender",
|
||||
text="Restart blender to reload",
|
||||
icon="BLANK1")
|
||||
updater.json_reset_restore()
|
||||
else:
|
||||
col = layout.column()
|
||||
col.scale_y = 0.7
|
||||
col.label(text="Addon successfully installed",
|
||||
icon="FILE_TICK")
|
||||
col.label(text="Restart blender to reload.", icon="BLANK1")
|
||||
col.label(text="Addon successfully installed", icon="FILE_TICK")
|
||||
alert_row = col.row()
|
||||
alert_row.alert = True
|
||||
alert_row.operator(
|
||||
"wm.quit_blender",
|
||||
text="Restart blender to reload",
|
||||
icon="BLANK1")
|
||||
|
||||
else:
|
||||
# reload addon, but still recommend they restart blender
|
||||
@ -520,8 +528,7 @@ class addon_updater_updated_successful(bpy.types.Operator):
|
||||
else:
|
||||
col = layout.column()
|
||||
col.scale_y = 0.7
|
||||
col.label(text="Addon successfully installed",
|
||||
icon="FILE_TICK")
|
||||
col.label(text="Addon successfully installed", icon="FILE_TICK")
|
||||
col.label(text="Consider restarting blender to fully reload.",
|
||||
icon="BLANK1")
|
||||
|
||||
@ -610,7 +617,6 @@ ran_update_sucess_popup = False
|
||||
# global var for preventing successive calls
|
||||
ran_background_check = False
|
||||
|
||||
|
||||
@persistent
|
||||
def updater_run_success_popup_handler(scene):
|
||||
global ran_update_sucess_popup
|
||||
@ -621,8 +627,12 @@ def updater_run_success_popup_handler(scene):
|
||||
return
|
||||
|
||||
try:
|
||||
if "scene_update_post" in dir(bpy.app.handlers):
|
||||
bpy.app.handlers.scene_update_post.remove(
|
||||
updater_run_success_popup_handler)
|
||||
else:
|
||||
bpy.app.handlers.depsgraph_update_post.remove(
|
||||
updater_run_success_popup_handler)
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -640,8 +650,12 @@ def updater_run_install_popup_handler(scene):
|
||||
return
|
||||
|
||||
try:
|
||||
if "scene_update_post" in dir(bpy.app.handlers):
|
||||
bpy.app.handlers.scene_update_post.remove(
|
||||
updater_run_install_popup_handler)
|
||||
else:
|
||||
bpy.app.handlers.depsgraph_update_post.remove(
|
||||
updater_run_install_popup_handler)
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -659,7 +673,7 @@ def updater_run_install_popup_handler(scene):
|
||||
# user probably manually installed to get the up to date addon
|
||||
# in here. Clear out the update flag using this function
|
||||
if updater.verbose:
|
||||
print("{} updater: appears user updated, clearing flag".format(
|
||||
print("{} updater: appears user updated, clearing flag".format(\
|
||||
updater.addon))
|
||||
updater.json_reset_restore()
|
||||
return
|
||||
@ -678,11 +692,24 @@ def background_update_callback(update_ready):
|
||||
return
|
||||
if update_ready != True:
|
||||
return
|
||||
if updater_run_install_popup_handler not in \
|
||||
bpy.app.handlers.scene_update_post and \
|
||||
ran_autocheck_install_popup == False:
|
||||
|
||||
# see if we need add to the update handler to trigger the popup
|
||||
handlers = []
|
||||
if "scene_update_post" in dir(bpy.app.handlers): # 2.7x
|
||||
handlers = bpy.app.handlers.scene_update_post
|
||||
else: # 2.8x
|
||||
handlers = bpy.app.handlers.depsgraph_update_post
|
||||
in_handles = updater_run_install_popup_handler in handlers
|
||||
|
||||
if in_handles or ran_autocheck_install_popup:
|
||||
return
|
||||
|
||||
if "scene_update_post" in dir(bpy.app.handlers): # 2.7x
|
||||
bpy.app.handlers.scene_update_post.append(
|
||||
updater_run_install_popup_handler)
|
||||
else: # 2.8x
|
||||
bpy.app.handlers.depsgraph_update_post.append(
|
||||
updater_run_install_popup_handler)
|
||||
ran_autocheck_install_popup = True
|
||||
|
||||
|
||||
@ -706,7 +733,6 @@ def post_update_callback(module_name, res=None):
|
||||
# ie if "auto_reload_post_update" == True, comment out this code
|
||||
if updater.verbose:
|
||||
print("{} updater: Running post update callback".format(updater.addon))
|
||||
# bpy.app.handlers.scene_update_post.append(updater_run_success_popup_handler)
|
||||
|
||||
atr = addon_updater_updated_successful.bl_idname.split(".")
|
||||
getattr(getattr(bpy.ops, atr[0]),atr[1])('INVOKE_DEFAULT')
|
||||
@ -760,7 +786,7 @@ def check_for_update_background():
|
||||
# this function should take a bool input, if true: update ready
|
||||
# if false, no update ready
|
||||
if updater.verbose:
|
||||
print("{} updater: Running background check for update".format(
|
||||
print("{} updater: Running background check for update".format(\
|
||||
updater.addon))
|
||||
updater.check_for_update_async(background_update_callback)
|
||||
ran_background_check = True
|
||||
@ -791,8 +817,7 @@ def check_for_update_nonthreaded(self, context):
|
||||
atr = addon_updater_install_popup.bl_idname.split(".")
|
||||
getattr(getattr(bpy.ops, atr[0]),atr[1])('INVOKE_DEFAULT')
|
||||
else:
|
||||
if updater.verbose:
|
||||
print("No update ready")
|
||||
if updater.verbose: print("No update ready")
|
||||
self.report({'INFO'}, "No update ready")
|
||||
|
||||
|
||||
@ -806,22 +831,36 @@ def showReloadPopup():
|
||||
saved_state = updater.json
|
||||
global ran_update_sucess_popup
|
||||
|
||||
a = saved_state != None
|
||||
b = "just_updated" in saved_state
|
||||
c = saved_state["just_updated"]
|
||||
has_state = saved_state != None
|
||||
just_updated = "just_updated" in saved_state
|
||||
updated_info = saved_state["just_updated"]
|
||||
|
||||
if not (has_state and just_updated and updated_info):
|
||||
return
|
||||
|
||||
if a and b and c:
|
||||
updater.json_reset_postupdate() # so this only runs once
|
||||
|
||||
# no handlers in this case
|
||||
if updater.auto_reload_post_update == False:
|
||||
return
|
||||
|
||||
if updater_run_success_popup_handler not in \
|
||||
bpy.app.handlers.scene_update_post \
|
||||
and ran_update_sucess_popup == False:
|
||||
# see if we need add to the update handler to trigger the popup
|
||||
handlers = []
|
||||
if "scene_update_post" in dir(bpy.app.handlers): # 2.7x
|
||||
handlers = bpy.app.handlers.scene_update_post
|
||||
else: # 2.8x
|
||||
handlers = bpy.app.handlers.depsgraph_update_post
|
||||
in_handles = updater_run_success_popup_handler in handlers
|
||||
|
||||
if in_handles or ran_update_sucess_popup is True:
|
||||
return
|
||||
|
||||
if "scene_update_post" in dir(bpy.app.handlers): # 2.7x
|
||||
bpy.app.handlers.scene_update_post.append(
|
||||
updater_run_success_popup_handler)
|
||||
else: # 2.8x
|
||||
bpy.app.handlers.depsgraph_update_post.append(
|
||||
updater_run_success_popup_handler)
|
||||
ran_update_sucess_popup = True
|
||||
|
||||
|
||||
@ -847,9 +886,14 @@ def update_notice_box_ui(self, context):
|
||||
layout = self.layout
|
||||
box = layout.box()
|
||||
col = box.column()
|
||||
col.scale_y = 0.7
|
||||
col.label(text="Restart blender", icon="ERROR")
|
||||
alert_row = col.row()
|
||||
alert_row.alert = True
|
||||
alert_row.operator(
|
||||
"wm.quit_blender",
|
||||
text="Restart blender",
|
||||
icon="ERROR")
|
||||
col.label(text="to complete update")
|
||||
|
||||
return
|
||||
|
||||
# if user pressed ignore, don't draw the box
|
||||
@ -913,10 +957,14 @@ def update_settings_ui(self, context, element=None):
|
||||
if updater.auto_reload_post_update == False:
|
||||
saved_state = updater.json
|
||||
if "just_updated" in saved_state and saved_state["just_updated"] == True:
|
||||
row.label(text="Restart blender to complete update", icon="ERROR")
|
||||
row.alert = True
|
||||
row.operator(
|
||||
"wm.quit_blender",
|
||||
text="Restart blender to complete update",
|
||||
icon="ERROR")
|
||||
return
|
||||
|
||||
split = layout_split(row, factor=0.3)
|
||||
split = layout_split(row, factor=0.4)
|
||||
subcol = split.column()
|
||||
subcol.prop(settings, "auto_check_update")
|
||||
subcol = split.column()
|
||||
@ -931,9 +979,11 @@ def update_settings_ui(self, context, element=None):
|
||||
checkcol = subrow.column(align=True)
|
||||
checkcol.prop(settings,"updater_intrval_days")
|
||||
checkcol = subrow.column(align=True)
|
||||
checkcol.prop(settings, "updater_intrval_hours")
|
||||
checkcol = subrow.column(align=True)
|
||||
checkcol.prop(settings, "updater_intrval_minutes")
|
||||
|
||||
# Consider un-commenting for local dev (e.g. to set shorter intervals)
|
||||
# checkcol.prop(settings,"updater_intrval_hours")
|
||||
# checkcol = subrow.column(align=True)
|
||||
# checkcol.prop(settings,"updater_intrval_minutes")
|
||||
|
||||
# checking / managing updates
|
||||
row = box.row()
|
||||
@ -1073,7 +1123,11 @@ def update_settings_ui_condensed(self, context, element=None):
|
||||
if updater.auto_reload_post_update == False:
|
||||
saved_state = updater.json
|
||||
if "just_updated" in saved_state and saved_state["just_updated"] == True:
|
||||
row.label(text="Restart blender to complete update", icon="ERROR")
|
||||
row.alert = True # mark red
|
||||
row.operator(
|
||||
"wm.quit_blender",
|
||||
text="Restart blender to complete update",
|
||||
icon="ERROR")
|
||||
return
|
||||
|
||||
col = row.column()
|
||||
@ -1194,13 +1248,11 @@ def skip_tag_function(self, tag):
|
||||
|
||||
if self.include_branches == True:
|
||||
for branch in self.include_branch_list:
|
||||
if tag["name"].lower() == branch:
|
||||
return False
|
||||
if tag["name"].lower() == branch: return False
|
||||
|
||||
# function converting string to tuple, ignoring e.g. leading 'v'
|
||||
tupled = self.version_tuple_from_text(tag["name"])
|
||||
if type(tupled) != type((1, 2, 3)):
|
||||
return True
|
||||
if type(tupled) != type( (1,2,3) ): return True
|
||||
|
||||
# select the min tag version - change tuple accordingly
|
||||
if self.version_min_update != None:
|
||||
@ -1272,7 +1324,9 @@ def register(bl_info):
|
||||
updater.clear_state() # clear internal vars, avoids reloading oddities
|
||||
|
||||
# confirm your updater "engine" (Github is default if not specified)
|
||||
# updater.engine = "Github"
|
||||
updater.engine = "GitLab"
|
||||
# updater.engine = "Bitbucket"
|
||||
|
||||
# If using private repository, indicate the token here
|
||||
# Must be set after assigning the engine.
|
||||
@ -1286,7 +1340,6 @@ def register(bl_info):
|
||||
|
||||
# choose your own repository, must match git name
|
||||
updater.repo = "10515801"
|
||||
|
||||
#updater.addon = # define at top of module, MUST be done first
|
||||
|
||||
# Website for manual addon download, optional but recommended to set
|
||||
@ -1295,7 +1348,7 @@ def register(bl_info):
|
||||
# Addon subfolder path
|
||||
# "sample/path/to/addon"
|
||||
# default is "" or None, meaning root
|
||||
updater.subfolder_path = "multi-user"
|
||||
updater.subfolder_path = "multi_user"
|
||||
|
||||
# used to check/compare versions
|
||||
updater.current_version = bl_info["version"]
|
||||
@ -1307,7 +1360,7 @@ def register(bl_info):
|
||||
|
||||
# Optional, consider turning off for production or allow as an option
|
||||
# This will print out additional debugging info to the console
|
||||
updater.verbose = True # make False for production default
|
||||
updater.verbose = False # make False for production default
|
||||
|
||||
# Optional, customize where the addon updater processing subfolder is,
|
||||
# essentially a staging folder used by the updater on its own
|
||||
@ -1368,11 +1421,11 @@ def register(bl_info):
|
||||
# the "install {branch}/older version" operator.
|
||||
updater.include_branches = True
|
||||
|
||||
# (GitHub/Gitlab only) This options allows the user to use releases over tags for data,
|
||||
# (GitHub only) This options allows the user to use releases over tags for data,
|
||||
# which enables pulling down release logs/notes, as well as specify installs from
|
||||
# release-attached zips (instead of just the auto-packaged code generated with
|
||||
# a release/tag). Setting has no impact on BitBucket or GitLab repos
|
||||
updater.use_releases = True
|
||||
updater.use_releases = False
|
||||
# note: Releases always have a tag, but a tag may not always be a release
|
||||
# Therefore, setting True above will filter out any non-annoted tags
|
||||
# note 2: Using this option will also display the release name instead of
|
||||
@ -1382,8 +1435,7 @@ def register(bl_info):
|
||||
# updater.include_branch_list defaults to ['master'] branch if set to none
|
||||
# example targeting another multiple branches allowed to pull from
|
||||
# updater.include_branch_list = ['master', 'dev'] # example with two branches
|
||||
# None is the equivalent to setting ['master']
|
||||
updater.include_branch_list = None
|
||||
updater.include_branch_list = ['master','develop'] # None is the equivalent to setting ['master']
|
||||
|
||||
# Only allow manual install, thus prompting the user to open
|
||||
# the addon's web page to download, specifically: updater.website
|
||||
@ -1408,7 +1460,7 @@ def register(bl_info):
|
||||
# Set the min and max versions allowed to install.
|
||||
# Optional, default None
|
||||
# min install (>=) will install this and higher
|
||||
updater.version_min_update = (0, 0, 1)
|
||||
updater.version_min_update = (0,0,3)
|
||||
# updater.version_min_update = None # if not wanting to define a min
|
||||
|
||||
# max install (<) will install strictly anything lower
|
||||
@ -1421,6 +1473,11 @@ def register(bl_info):
|
||||
# Function defined above, customize as appropriate per repository; not required
|
||||
updater.select_link = select_link_function
|
||||
|
||||
# Recommended false to encourage blender restarts on update completion
|
||||
# Setting this option to True is NOT as stable as false (could cause
|
||||
# blender crashes)
|
||||
updater.auto_reload_post_update = False
|
||||
|
||||
# The register line items for all operators/panels
|
||||
# If using bpy.utils.register_module(__name__) to register elsewhere
|
||||
# in the addon, delete these lines (also from unregister)
|
||||
|
@ -326,7 +326,7 @@ class SessionPrefs(bpy.types.AddonPreferences):
|
||||
|
||||
if self.category == 'UPDATE':
|
||||
from . import addon_updater_ops
|
||||
addon_updater_ops.update_settings_ui_condensed(self, context)
|
||||
addon_updater_ops.update_settings_ui(self, context)
|
||||
|
||||
def generate_supported_types(self):
|
||||
self.supported_datablocks.clear()
|
||||
|
Reference in New Issue
Block a user