Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Dinges <blender@dingto.org>2021-11-24 16:29:16 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2021-12-07 17:47:29 +0300
commit69c817b87a25022e7413a635c60270a2516d4403 (patch)
treed0b41138488660049bd91c4a3a23f47cba439bfa
parent0521e90f2d7769510b9ce0ececdc1baf9cc9ca52 (diff)
Magic UV: Remove online updater
Add-ons should not connect to external services outside of blender.org See new key requirements: https://wiki.blender.org/wiki/Process/Addons
-rw-r--r--magic_uv/__init__.py4
-rw-r--r--magic_uv/preferences.py21
-rw-r--r--magic_uv/updater.py144
-rw-r--r--magic_uv/utils/__init__.py2
-rw-r--r--magic_uv/utils/addon_updater.py372
5 files changed, 0 insertions, 543 deletions
diff --git a/magic_uv/__init__.py b/magic_uv/__init__.py
index d0b8ae45..f31ad26b 100644
--- a/magic_uv/__init__.py
+++ b/magic_uv/__init__.py
@@ -52,7 +52,6 @@ if "bpy" in locals():
importlib.reload(ui)
importlib.reload(properites)
importlib.reload(preferences)
- importlib.reload(updater)
else:
import bpy
from . import common
@@ -61,14 +60,11 @@ else:
from . import ui
from . import properites
from . import preferences
- from . import updater
import bpy
def register():
- updater.register_updater(bl_info)
-
utils.bl_class_registry.BlClassRegistry.register()
properites.init_props(bpy.types.Scene)
user_prefs = utils.compatibility.get_user_preferences(bpy.context)
diff --git a/magic_uv/preferences.py b/magic_uv/preferences.py
index 21f70508..7d6ac957 100644
--- a/magic_uv/preferences.py
+++ b/magic_uv/preferences.py
@@ -59,9 +59,7 @@ from .ui.IMAGE_MT_uvs import (
MUV_MT_UVInspection,
)
from .utils.bl_class_registry import BlClassRegistry
-from .utils.addon_updater import AddonUpdaterManager
from .utils import compatibility as compat
-from . import updater
def view3d_uvmap_menu_fn(self, context):
@@ -169,14 +167,6 @@ def remove_builtin_menu():
bpy.types.VIEW3D_MT_uv_map.remove(view3d_uvmap_menu_fn)
-def get_update_candidate_branches(_, __):
- manager = AddonUpdaterManager.get_instance()
- if not manager.candidate_checked():
- return []
-
- return [(name, name, "") for name in manager.get_candidate_branch_names()]
-
-
def set_debug_mode(self, value):
self['enable_debug_mode'] = value
@@ -301,7 +291,6 @@ class MUV_Preferences(AddonPreferences):
items=[
('INFO', "Information", "Information about this add-on"),
('CONFIG', "Configuration", "Configuration about this add-on"),
- ('UPDATE', "Update", "Update this add-on"),
],
default='INFO'
)
@@ -336,13 +325,6 @@ class MUV_Preferences(AddonPreferences):
default=False
)
- # for add-on updater
- updater_branch_to_update = EnumProperty(
- name="branch",
- description="Target branch to update add-on",
- items=get_update_candidate_branches
- )
-
def draw(self, _):
layout = self.layout
@@ -520,6 +502,3 @@ class MUV_Preferences(AddonPreferences):
col.prop(self, "uv_bounding_box_cp_size")
col.prop(self, "uv_bounding_box_cp_react_size")
layout.separator()
-
- elif self.category == 'UPDATE':
- updater.draw_updater_ui(self)
diff --git a/magic_uv/updater.py b/magic_uv/updater.py
deleted file mode 100644
index 72d85766..00000000
--- a/magic_uv/updater.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# <pep8-80 compliant>
-
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-__author__ = "Nutti <nutti.metro@gmail.com>"
-__status__ = "production"
-__version__ = "6.5"
-__date__ = "6 Mar 2021"
-
-import os
-
-import bpy
-from bpy.props import (
- StringProperty,
-)
-
-from .utils.bl_class_registry import BlClassRegistry
-from .utils.addon_updater import (
- AddonUpdaterManager,
- AddonUpdaterConfig,
- get_separator,
-)
-from .utils import compatibility as compat
-
-
-@BlClassRegistry()
-class MUV_OT_CheckAddonUpdate(bpy.types.Operator):
- bl_idname = "uv.muv_check_addon_update"
- bl_label = "Check Update"
- bl_description = "Check Add-on Update"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, _):
- updater = AddonUpdaterManager.get_instance()
- updater.check_update_candidate()
-
- return {'FINISHED'}
-
-
-@BlClassRegistry()
-@compat.make_annotations
-class MUV_OT_UpdateAddon(bpy.types.Operator):
- bl_idname = "uv.muv_update_addon"
- bl_label = "Update"
- bl_description = "Update Add-on"
- bl_options = {'REGISTER', 'UNDO'}
-
- branch_name = StringProperty(
- name="Branch Name",
- description="Branch name to update",
- default="",
- )
-
- def execute(self, _):
- updater = AddonUpdaterManager.get_instance()
- updater.update(self.branch_name)
-
- return {'FINISHED'}
-
-
-def draw_updater_ui(prefs_obj):
- layout = prefs_obj.layout
- updater = AddonUpdaterManager.get_instance()
-
- layout.separator()
-
- if not updater.candidate_checked():
- col = layout.column()
- col.scale_y = 2
- row = col.row()
- row.operator(MUV_OT_CheckAddonUpdate.bl_idname,
- text="Check 'Magic UV' add-on update",
- icon='FILE_REFRESH')
- else:
- row = layout.row(align=True)
- row.scale_y = 2
- col = row.column()
- col.operator(MUV_OT_CheckAddonUpdate.bl_idname,
- text="Check 'Magic UV' add-on update",
- icon='FILE_REFRESH')
- col = row.column()
- if updater.latest_version() != "":
- col.enabled = True
- ops = col.operator(
- MUV_OT_UpdateAddon.bl_idname,
- text="Update to the latest release version (version: {})"
- .format(updater.latest_version()),
- icon='TRIA_DOWN_BAR')
- ops.branch_name = updater.latest_version()
- else:
- col.enabled = False
- col.operator(MUV_OT_UpdateAddon.bl_idname,
- text="No updates are available.")
-
- layout.separator()
- layout.label(text="Manual Update:")
- row = layout.row(align=True)
- row.prop(prefs_obj, "updater_branch_to_update", text="Target")
- ops = row.operator(
- MUV_OT_UpdateAddon.bl_idname, text="Update",
- icon='TRIA_DOWN_BAR')
- ops.branch_name = prefs_obj.updater_branch_to_update
-
- layout.separator()
- if updater.has_error():
- box = layout.box()
- box.label(text=updater.error(), icon='CANCEL')
- elif updater.has_info():
- box = layout.box()
- box.label(text=updater.info(), icon='ERROR')
-
-
-def register_updater(bl_info):
- config = AddonUpdaterConfig()
- config.owner = "nutti"
- config.repository = "Magic-UV"
- config.current_addon_path = os.path.dirname(os.path.realpath(__file__))
- config.branches = ["master"]
- config.addon_directory = \
- config.current_addon_path[
- :config.current_addon_path.rfind(get_separator())]
- config.min_release_version = bl_info["version"]
- config.default_target_addon_path = "magic_uv"
- config.target_addon_path = {
- "master": "src{}magic_uv".format(get_separator()),
- }
- updater = AddonUpdaterManager.get_instance()
- updater.init(bl_info, config)
diff --git a/magic_uv/utils/__init__.py b/magic_uv/utils/__init__.py
index 776c7564..87c6eacb 100644
--- a/magic_uv/utils/__init__.py
+++ b/magic_uv/utils/__init__.py
@@ -25,12 +25,10 @@ __date__ = "6 Mar 2021"
if "bpy" in locals():
import importlib
- importlib.reload(addon_updater)
importlib.reload(bl_class_registry)
importlib.reload(compatibility)
importlib.reload(property_class_registry)
else:
- from . import addon_updater
from . import bl_class_registry
from . import compatibility
from . import property_class_registry
diff --git a/magic_uv/utils/addon_updater.py b/magic_uv/utils/addon_updater.py
deleted file mode 100644
index 8c1601b8..00000000
--- a/magic_uv/utils/addon_updater.py
+++ /dev/null
@@ -1,372 +0,0 @@
-# <pep8-80 compliant>
-
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-__author__ = "Nutti <nutti.metro@gmail.com>"
-__status__ = "production"
-__version__ = "6.5"
-__date__ = "6 Mar 2021"
-
-from threading import Lock
-import urllib
-import urllib.request
-import ssl
-import json
-import os
-import zipfile
-import shutil
-import datetime
-
-
-def get_separator():
- if os.name == "nt":
- return "\\"
- return "/"
-
-
-def _request(url, json_decode=True):
- # pylint: disable=W0212
- ssl._create_default_https_context = ssl._create_unverified_context
- req = urllib.request.Request(url)
-
- try:
- result = urllib.request.urlopen(req)
- except urllib.error.HTTPError as e:
- raise RuntimeError("HTTP error ({})".format(str(e.code)))
- except urllib.error.URLError as e:
- raise RuntimeError("URL error ({})".format(str(e.reason)))
-
- data = result.read()
- result.close()
-
- if json_decode:
- try:
- return json.JSONDecoder().decode(data.decode())
- except Exception as e:
- raise RuntimeError("API response has invalid JSON format ({})"
- .format(str(e)))
-
- return data.decode()
-
-
-def _download(url, path):
- try:
- urllib.request.urlretrieve(url, path)
- except urllib.error.HTTPError as e:
- raise RuntimeError("HTTP error ({})".format(str(e.code)))
- except urllib.error.URLError as e:
- raise RuntimeError("URL error ({})".format(str(e.reason)))
-
-
-def _make_workspace_path(addon_dir):
- return addon_dir + get_separator() + "addon_updater_workspace"
-
-
-def _make_workspace(addon_dir):
- dir_path = _make_workspace_path(addon_dir)
- os.mkdir(dir_path)
-
-
-def _make_temp_addon_path(addon_dir, url):
- filename = url.split("/")[-1]
- filepath = _make_workspace_path(addon_dir) + get_separator() + filename
- return filepath
-
-
-def _download_addon(addon_dir, url):
- filepath = _make_temp_addon_path(addon_dir, url)
- _download(url, filepath)
-
-
-def _replace_addon(addon_dir, info, current_addon_path, offset_path=""):
- # remove current add-on
- if os.path.isfile(current_addon_path):
- os.remove(current_addon_path)
- elif os.path.isdir(current_addon_path):
- shutil.rmtree(current_addon_path)
-
- # replace to the new add-on
- workspace_path = _make_workspace_path(addon_dir)
- tmp_addon_path = _make_temp_addon_path(addon_dir, info.url)
- _, ext = os.path.splitext(tmp_addon_path)
- if ext == ".zip":
- with zipfile.ZipFile(tmp_addon_path) as zf:
- zf.extractall(workspace_path)
- if offset_path != "":
- src = workspace_path + get_separator() + offset_path
- dst = addon_dir
- shutil.move(src, dst)
- elif ext == ".py":
- shutil.move(tmp_addon_path, addon_dir)
- else:
- raise RuntimeError("Unsupported file extension. (ext: {})".format(ext))
-
-
-def _get_all_releases_data(owner, repository):
- url = "https://api.github.com/repos/{}/{}/releases"\
- .format(owner, repository)
- data = _request(url)
-
- return data
-
-
-def _get_all_branches_data(owner, repository):
- url = "https://api.github.com/repos/{}/{}/branches"\
- .format(owner, repository)
- data = _request(url)
-
- return data
-
-
-def _parse_release_version(version):
- return [int(c) for c in version[1:].split(".")]
-
-
-# ver1 > ver2 : > 0
-# ver1 == ver2 : == 0
-# ver1 < ver2 : < 0
-def _compare_version(ver1, ver2):
- if len(ver1) < len(ver2):
- ver1.extend([-1 for _ in range(len(ver2) - len(ver1))])
- elif len(ver1) > len(ver2):
- ver2.extend([-1 for _ in range(len(ver1) - len(ver2))])
-
- def comp(v1, v2, idx):
- if len(v1) == idx:
- return 0 # v1 == v2
-
- if v1[idx] > v2[idx]:
- return 1 # v1 > v2
- if v1[idx] < v2[idx]:
- return -1 # v1 < v2
-
- return comp(v1, v2, idx + 1)
-
- return comp(ver1, ver2, 0)
-
-
-class AddonUpdaterConfig:
- def __init__(self):
- # Name of owner
- self.owner = ""
-
- # Name of repository
- self.repository = ""
-
- # Additional branch for update candidate
- self.branches = []
-
- # Set minimum release version for update candidate.
- # e.g. (5, 2) if your release tag name is "v5.2"
- # If you specify (-1, -1), ignore versions less than current add-on
- # version specified in bl_info.
- self.min_release_version = (-1, -1)
-
- # Target add-on path
- # {"branch/tag": "add-on path"}
- self.target_addon_path = {}
-
- # Default target add-on path.
- # Search this path if branch/tag is not found in
- # self.target_addon_path.
- self.default_target_addon_path = ""
-
- # Current add-on path
- self.current_addon_path = ""
-
- # Blender add-on directory
- self.addon_directory = ""
-
-
-class UpdateCandidateInfo:
- def __init__(self):
- self.name = ""
- self.url = ""
- self.group = "" # BRANCH|RELEASE
-
-
-class AddonUpdaterManager:
- __inst = None
- __lock = Lock()
-
- __initialized = False
- __bl_info = None
- __config = None
- __update_candidate = []
- __candidate_checked = False
- __error = ""
- __info = ""
-
- def __init__(self):
- raise NotImplementedError("Not allowed to call constructor")
-
- @classmethod
- def __internal_new(cls):
- return super().__new__(cls)
-
- @classmethod
- def get_instance(cls):
- if not cls.__inst:
- with cls.__lock:
- if not cls.__inst:
- cls.__inst = cls.__internal_new()
-
- return cls.__inst
-
- def init(self, bl_info, config):
- self.__bl_info = bl_info
- self.__config = config
- self.__update_candidate = []
- self.__candidate_checked = False
- self.__error = ""
- self.__info = ""
- self.__initialized = True
-
- def initialized(self):
- return self.__initialized
-
- def candidate_checked(self):
- return self.__candidate_checked
-
- def check_update_candidate(self):
- if not self.initialized():
- raise RuntimeError("AddonUpdaterManager must be initialized")
-
- self.__update_candidate = []
- self.__candidate_checked = False
-
- try:
- # setup branch information
- branches = _get_all_branches_data(self.__config.owner,
- self.__config.repository)
- for b in branches:
- if b["name"] in self.__config.branches:
- info = UpdateCandidateInfo()
- info.name = b["name"]
- info.url = "https://github.com/{}/{}/archive/{}.zip"\
- .format(self.__config.owner,
- self.__config.repository, b["name"])
- info.group = 'BRANCH'
- self.__update_candidate.append(info)
-
- # setup release information
- releases = _get_all_releases_data(self.__config.owner,
- self.__config.repository)
- for r in releases:
- if _compare_version(_parse_release_version(r["tag_name"]),
- self.__config.min_release_version) > 0:
- info = UpdateCandidateInfo()
- info.name = r["tag_name"]
- info.url = r["assets"][0]["browser_download_url"]
- info.group = 'RELEASE'
- self.__update_candidate.append(info)
- except RuntimeError as e:
- self.__error = "Failed to check update {}. ({})"\
- .format(str(e), datetime.datetime.now())
-
- self.__info = "Checked update. ({})"\
- .format(datetime.datetime.now())
-
- self.__candidate_checked = True
-
- def has_error(self):
- return self.__error != ""
-
- def error(self):
- return self.__error
-
- def has_info(self):
- return self.__info != ""
-
- def info(self):
- return self.__info
-
- def update(self, version_name):
- if not self.initialized():
- raise RuntimeError("AddonUpdaterManager must be initialized.")
-
- if not self.candidate_checked():
- raise RuntimeError("Update candidate is not checked.")
-
- info = None
- for info in self.__update_candidate:
- if info.name == version_name:
- break
- else:
- raise RuntimeError("{} is not found in update candidate"
- .format(version_name))
-
- if info is None:
- raise RuntimeError("Not found any update candidates")
-
- try:
- # create workspace
- _make_workspace(self.__config.addon_directory)
- # download add-on
- _download_addon(self.__config.addon_directory, info.url)
-
- # get add-on path
- if info.name in self.__config.target_addon_path:
- addon_path = self.__config.target_addon_path[info.name]
- else:
- addon_path = self.__config.default_target_addon_path
-
- # replace add-on
- offset_path = ""
- if info.group == 'BRANCH':
- offset_path = "{}-{}{}{}".format(
- self.__config.repository, info.name, get_separator(),
- addon_path)
- elif info.group == 'RELEASE':
- offset_path = addon_path
- _replace_addon(self.__config.addon_directory,
- info, self.__config.current_addon_path,
- offset_path)
-
- self.__info = "Updated to {}. ({})" \
- .format(info.name, datetime.datetime.now())
- except RuntimeError as e:
- self.__error = "Failed to update {}. ({})"\
- .format(str(e), datetime.datetime.now())
-
- shutil.rmtree(_make_workspace_path(self.__config.addon_directory))
-
- def get_candidate_branch_names(self):
- if not self.initialized():
- raise RuntimeError("AddonUpdaterManager must be initialized.")
-
- if not self.candidate_checked():
- raise RuntimeError("Update candidate is not checked.")
-
- return [info.name for info in self.__update_candidate]
-
- def latest_version(self):
- release_versions = [info.name
- for info in self.__update_candidate
- if info.group == 'RELEASE']
-
- latest = ""
- for version in release_versions:
- if latest == "":
- latest = version
- elif _compare_version(_parse_release_version(version),
- _parse_release_version(latest)) > 0:
- latest = version
-
- return latest