formatting
This commit is contained in:
parent
a681245093
commit
ff85c93551
5 changed files with 641 additions and 549 deletions
312
addon_updater.py
312
addon_updater.py
|
@ -54,8 +54,8 @@ class SingletonUpdater:
|
|||
needed throughout the addon. It implements all the interfaces for running
|
||||
updates.
|
||||
"""
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self):
|
||||
self._engine = ForgejoEngine()
|
||||
self._user = None
|
||||
self._repo = None
|
||||
|
@ -68,7 +68,7 @@ class SingletonUpdater:
|
|||
self._latest_release = None
|
||||
self._use_releases = False
|
||||
self._include_branches = False
|
||||
self._include_branch_list = ['master']
|
||||
self._include_branch_list = ["master"]
|
||||
self._include_branch_auto_check = False
|
||||
self._manual_only = False
|
||||
self._version_min_update = None
|
||||
|
@ -110,7 +110,8 @@ class SingletonUpdater:
|
|||
self._addon = __package__.lower()
|
||||
self._addon_package = __package__ # Must not change.
|
||||
self._updater_path = os.path.join(
|
||||
os.path.dirname(__file__), self._addon + "_updater")
|
||||
os.path.dirname(__file__), self._addon + "_updater"
|
||||
)
|
||||
self._addon_root = os.path.dirname(__file__)
|
||||
self._json = dict()
|
||||
self._error = None
|
||||
|
@ -202,11 +203,13 @@ class SingletonUpdater:
|
|||
|
||||
@property
|
||||
def check_interval(self):
|
||||
return (self._check_interval_enabled,
|
||||
self._check_interval_months,
|
||||
self._check_interval_days,
|
||||
self._check_interval_hours,
|
||||
self._check_interval_minutes)
|
||||
return (
|
||||
self._check_interval_enabled,
|
||||
self._check_interval_months,
|
||||
self._check_interval_days,
|
||||
self._check_interval_hours,
|
||||
self._check_interval_minutes,
|
||||
)
|
||||
|
||||
@property
|
||||
def current_version(self):
|
||||
|
@ -221,12 +224,10 @@ class SingletonUpdater:
|
|||
try:
|
||||
tuple(tuple_values)
|
||||
except:
|
||||
raise ValueError(
|
||||
"current_version must be a tuple of integers")
|
||||
raise ValueError("current_version must be a tuple of integers")
|
||||
for i in tuple_values:
|
||||
if type(i) is not int:
|
||||
raise ValueError(
|
||||
"current_version must be a tuple of integers")
|
||||
raise ValueError("current_version must be a tuple of integers")
|
||||
self._current_version = tuple(tuple_values)
|
||||
|
||||
@property
|
||||
|
@ -285,15 +286,15 @@ class SingletonUpdater:
|
|||
def include_branch_list(self, value):
|
||||
try:
|
||||
if value is None:
|
||||
self._include_branch_list = ['master']
|
||||
self._include_branch_list = ["master"]
|
||||
elif not isinstance(value, list) or len(value) == 0:
|
||||
raise ValueError(
|
||||
"include_branch_list should be a list of valid branches")
|
||||
"include_branch_list should be a list of valid branches"
|
||||
)
|
||||
else:
|
||||
self._include_branch_list = value
|
||||
except:
|
||||
raise ValueError(
|
||||
"include_branch_list should be a list of valid branches")
|
||||
raise ValueError("include_branch_list should be a list of valid branches")
|
||||
|
||||
@property
|
||||
def include_branches(self):
|
||||
|
@ -362,8 +363,7 @@ class SingletonUpdater:
|
|||
if value is None:
|
||||
self._remove_pre_update_patterns = list()
|
||||
elif not isinstance(value, list):
|
||||
raise ValueError(
|
||||
"remove_pre_update_patterns needs to be in a list format")
|
||||
raise ValueError("remove_pre_update_patterns needs to be in a list format")
|
||||
else:
|
||||
self._remove_pre_update_patterns = value
|
||||
|
||||
|
@ -548,8 +548,7 @@ class SingletonUpdater:
|
|||
tag_names.append(tag["name"])
|
||||
return tag_names
|
||||
|
||||
def set_check_interval(self, enabled=False,
|
||||
months=0, days=14, hours=0, minutes=0):
|
||||
def set_check_interval(self, enabled=False, months=0, days=14, hours=0, minutes=0):
|
||||
"""Set the time interval between automated checks, and if enabled.
|
||||
|
||||
Has enabled = False as default to not check against frequency,
|
||||
|
@ -582,7 +581,8 @@ class SingletonUpdater:
|
|||
|
||||
def __str__(self):
|
||||
return "Updater, with user: {a}, repository: {b}, url: {c}".format(
|
||||
a=self._user, b=self._repo, c=self.form_repo_url())
|
||||
a=self._user, b=self._repo, c=self.form_repo_url()
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# API-related functions
|
||||
|
@ -621,10 +621,7 @@ class SingletonUpdater:
|
|||
temp_branches.reverse()
|
||||
for branch in temp_branches:
|
||||
request = self.form_branch_url(branch)
|
||||
include = {
|
||||
"name": branch.title(),
|
||||
"zipball_url": request
|
||||
}
|
||||
include = {"name": branch.title(), "zipball_url": request}
|
||||
self._tags = [include] + self._tags # append to front
|
||||
|
||||
if self._tags is None:
|
||||
|
@ -643,13 +640,18 @@ class SingletonUpdater:
|
|||
if not self._error:
|
||||
self._tag_latest = self._tags[0]
|
||||
branch = self._include_branch_list[0]
|
||||
self.print_verbose("{} branch found, no releases: {}".format(
|
||||
branch, self._tags[0]))
|
||||
self.print_verbose(
|
||||
"{} branch found, no releases: {}".format(branch, self._tags[0])
|
||||
)
|
||||
|
||||
elif ((len(self._tags) - len(self._include_branch_list) == 0
|
||||
and self._include_branches)
|
||||
or (len(self._tags) == 0 and not self._include_branches)
|
||||
and self._prefiltered_tag_count > 0):
|
||||
elif (
|
||||
(
|
||||
len(self._tags) - len(self._include_branch_list) == 0
|
||||
and self._include_branches
|
||||
)
|
||||
or (len(self._tags) == 0 and not self._include_branches)
|
||||
and self._prefiltered_tag_count > 0
|
||||
):
|
||||
self._tag_latest = None
|
||||
self._error = "No releases available"
|
||||
self._error_msg = "No versions found within compatible version range"
|
||||
|
@ -659,13 +661,15 @@ class SingletonUpdater:
|
|||
if not self._include_branches:
|
||||
self._tag_latest = self._tags[0]
|
||||
self.print_verbose(
|
||||
"Most recent tag found:" + str(self._tags[0]['name']))
|
||||
"Most recent tag found:" + str(self._tags[0]["name"])
|
||||
)
|
||||
else:
|
||||
# Don't return branch if in list.
|
||||
n = len(self._include_branch_list)
|
||||
self._tag_latest = self._tags[n] # guaranteed at least len()=n+1
|
||||
self.print_verbose(
|
||||
"Most recent tag found:" + str(self._tags[n]['name']))
|
||||
"Most recent tag found:" + str(self._tags[n]["name"])
|
||||
)
|
||||
|
||||
def get_raw(self, url):
|
||||
"""All API calls to base url."""
|
||||
|
@ -680,13 +684,12 @@ class SingletonUpdater:
|
|||
# Setup private request headers if appropriate.
|
||||
if self._engine.token is not None:
|
||||
if self._engine.name == "gitlab":
|
||||
request.add_header('PRIVATE-TOKEN', self._engine.token)
|
||||
request.add_header("PRIVATE-TOKEN", self._engine.token)
|
||||
else:
|
||||
self.print_verbose("Tokens not setup for engine yet")
|
||||
|
||||
# Always set user agent.
|
||||
request.add_header(
|
||||
'User-Agent', "Python/" + str(platform.python_version()))
|
||||
request.add_header("User-Agent", "Python/" + str(platform.python_version()))
|
||||
|
||||
# Run the request.
|
||||
try:
|
||||
|
@ -747,8 +750,7 @@ class SingletonUpdater:
|
|||
error = None
|
||||
|
||||
# Make/clear the staging folder, to ensure the folder is always clean.
|
||||
self.print_verbose(
|
||||
"Preparing staging folder for download:\n" + str(local))
|
||||
self.print_verbose("Preparing staging folder for download:\n" + str(local))
|
||||
if os.path.isdir(local):
|
||||
try:
|
||||
shutil.rmtree(local)
|
||||
|
@ -782,17 +784,16 @@ class SingletonUpdater:
|
|||
# Setup private token if appropriate.
|
||||
if self._engine.token is not None:
|
||||
if self._engine.name == "gitlab":
|
||||
request.add_header('PRIVATE-TOKEN', self._engine.token)
|
||||
request.add_header("PRIVATE-TOKEN", self._engine.token)
|
||||
else:
|
||||
self.print_verbose(
|
||||
"Tokens not setup for selected engine yet")
|
||||
self.print_verbose("Tokens not setup for selected engine yet")
|
||||
|
||||
# Always set user agent
|
||||
request.add_header(
|
||||
'User-Agent', "Python/" + str(platform.python_version()))
|
||||
request.add_header("User-Agent", "Python/" + str(platform.python_version()))
|
||||
|
||||
self.url_retrieve(urllib.request.urlopen(request, context=context),
|
||||
self._source_zip)
|
||||
self.url_retrieve(
|
||||
urllib.request.urlopen(request, context=context), self._source_zip
|
||||
)
|
||||
# Add additional checks on file size being non-zero.
|
||||
self.print_verbose("Successfully downloaded update zip")
|
||||
return True
|
||||
|
@ -809,7 +810,8 @@ class SingletonUpdater:
|
|||
self.print_verbose("Backing up current addon folder")
|
||||
local = os.path.join(self._updater_path, "backup")
|
||||
tempdest = os.path.join(
|
||||
self._addon_root, os.pardir, self._addon + "_updater_backup_temp")
|
||||
self._addon_root, os.pardir, self._addon + "_updater_backup_temp"
|
||||
)
|
||||
|
||||
self.print_verbose("Backup destination path: " + str(local))
|
||||
|
||||
|
@ -818,7 +820,8 @@ class SingletonUpdater:
|
|||
shutil.rmtree(local)
|
||||
except:
|
||||
self.print_verbose(
|
||||
"Failed to removed previous backup folder, continuing")
|
||||
"Failed to removed previous backup folder, continuing"
|
||||
)
|
||||
self.print_trace()
|
||||
|
||||
# Remove the temp folder.
|
||||
|
@ -827,16 +830,17 @@ class SingletonUpdater:
|
|||
try:
|
||||
shutil.rmtree(tempdest)
|
||||
except:
|
||||
self.print_verbose(
|
||||
"Failed to remove existing temp folder, continuing")
|
||||
self.print_verbose("Failed to remove existing temp folder, continuing")
|
||||
self.print_trace()
|
||||
|
||||
# Make a full addon copy, temporarily placed outside the addon folder.
|
||||
if self._backup_ignore_patterns is not None:
|
||||
try:
|
||||
shutil.copytree(self._addon_root, tempdest,
|
||||
ignore=shutil.ignore_patterns(
|
||||
*self._backup_ignore_patterns))
|
||||
shutil.copytree(
|
||||
self._addon_root,
|
||||
tempdest,
|
||||
ignore=shutil.ignore_patterns(*self._backup_ignore_patterns),
|
||||
)
|
||||
except:
|
||||
print("Failed to create backup, still attempting update.")
|
||||
self.print_trace()
|
||||
|
@ -853,7 +857,8 @@ class SingletonUpdater:
|
|||
# Save the date for future reference.
|
||||
now = datetime.now()
|
||||
self._json["backup_date"] = "{m}-{d}-{yr}".format(
|
||||
m=now.strftime("%B"), d=now.day, yr=now.year)
|
||||
m=now.strftime("%B"), d=now.day, yr=now.year
|
||||
)
|
||||
self.save_updater_json()
|
||||
|
||||
def restore_backup(self):
|
||||
|
@ -861,7 +866,8 @@ class SingletonUpdater:
|
|||
self.print_verbose("Restoring backup, backing up current addon folder")
|
||||
backuploc = os.path.join(self._updater_path, "backup")
|
||||
tempdest = os.path.join(
|
||||
self._addon_root, os.pardir, self._addon + "_updater_backup_temp")
|
||||
self._addon_root, os.pardir, self._addon + "_updater_backup_temp"
|
||||
)
|
||||
tempdest = os.path.abspath(tempdest)
|
||||
|
||||
# Move instead contents back in place, instead of copy.
|
||||
|
@ -910,10 +916,8 @@ class SingletonUpdater:
|
|||
self._error_msg = "Failed to create extract directory"
|
||||
return -1
|
||||
|
||||
self.print_verbose(
|
||||
"Begin extracting source from zip:" + str(self._source_zip))
|
||||
self.print_verbose("Begin extracting source from zip:" + str(self._source_zip))
|
||||
with zipfile.ZipFile(self._source_zip, "r") as zfile:
|
||||
|
||||
if not zfile:
|
||||
self._error = "Install failed"
|
||||
self._error_msg = "Resulting file is not a zip, cannot extract"
|
||||
|
@ -923,19 +927,20 @@ class SingletonUpdater:
|
|||
# Now extract directly from the first subfolder (not root)
|
||||
# this avoids adding the first subfolder to the path length,
|
||||
# which can be too long if the download has the SHA in the name.
|
||||
zsep = '/' # Not using os.sep, always the / value even on windows.
|
||||
zsep = "/" # Not using os.sep, always the / value even on windows.
|
||||
for name in zfile.namelist():
|
||||
if zsep not in name:
|
||||
continue
|
||||
top_folder = name[:name.index(zsep) + 1]
|
||||
top_folder = name[: name.index(zsep) + 1]
|
||||
if name == top_folder + zsep:
|
||||
continue # skip top level folder
|
||||
sub_path = name[name.index(zsep) + 1:]
|
||||
sub_path = name[name.index(zsep) + 1 :]
|
||||
if name.endswith(zsep):
|
||||
try:
|
||||
os.mkdir(os.path.join(outdir, sub_path))
|
||||
self.print_verbose(
|
||||
"Extract - mkdir: " + os.path.join(outdir, sub_path))
|
||||
"Extract - mkdir: " + os.path.join(outdir, sub_path)
|
||||
)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
self._error = "Install failed"
|
||||
|
@ -947,7 +952,8 @@ class SingletonUpdater:
|
|||
data = zfile.read(name)
|
||||
outfile.write(data)
|
||||
self.print_verbose(
|
||||
"Extract - create: " + os.path.join(outdir, sub_path))
|
||||
"Extract - create: " + os.path.join(outdir, sub_path)
|
||||
)
|
||||
|
||||
self.print_verbose("Extracted source")
|
||||
|
||||
|
@ -959,8 +965,8 @@ class SingletonUpdater:
|
|||
return -1
|
||||
|
||||
if self._subfolder_path:
|
||||
self._subfolder_path.replace('/', os.path.sep)
|
||||
self._subfolder_path.replace('\\', os.path.sep)
|
||||
self._subfolder_path.replace("/", os.path.sep)
|
||||
self._subfolder_path.replace("\\", os.path.sep)
|
||||
|
||||
# Either directly in root of zip/one subfolder, or use specified path.
|
||||
if not os.path.isfile(os.path.join(unpath, "__init__.py")):
|
||||
|
@ -1018,25 +1024,31 @@ class SingletonUpdater:
|
|||
# Make sure that base is not a high level shared folder, but
|
||||
# is dedicated just to the addon itself.
|
||||
self.print_verbose(
|
||||
"clean=True, clearing addon folder to fresh install state")
|
||||
"clean=True, clearing addon folder to fresh install state"
|
||||
)
|
||||
|
||||
# Remove root files and folders (except update folder).
|
||||
files = [f for f in os.listdir(base)
|
||||
if os.path.isfile(os.path.join(base, f))]
|
||||
folders = [f for f in os.listdir(base)
|
||||
if os.path.isdir(os.path.join(base, f))]
|
||||
files = [
|
||||
f for f in os.listdir(base) if os.path.isfile(os.path.join(base, f))
|
||||
]
|
||||
folders = [
|
||||
f for f in os.listdir(base) if os.path.isdir(os.path.join(base, f))
|
||||
]
|
||||
|
||||
for f in files:
|
||||
os.remove(os.path.join(base, f))
|
||||
self.print_verbose(
|
||||
"Clean removing file {}".format(os.path.join(base, f)))
|
||||
"Clean removing file {}".format(os.path.join(base, f))
|
||||
)
|
||||
for f in folders:
|
||||
if os.path.join(base, f) is self._updater_path:
|
||||
continue
|
||||
shutil.rmtree(os.path.join(base, f))
|
||||
self.print_verbose(
|
||||
"Clean removing folder and contents {}".format(
|
||||
os.path.join(base, f)))
|
||||
os.path.join(base, f)
|
||||
)
|
||||
)
|
||||
|
||||
except Exception as err:
|
||||
error = "failed to create clean existing addon folder"
|
||||
|
@ -1047,8 +1059,9 @@ class SingletonUpdater:
|
|||
# but avoid removing/altering backup and updater file.
|
||||
for path, dirs, files in os.walk(base):
|
||||
# Prune ie skip updater folder.
|
||||
dirs[:] = [d for d in dirs
|
||||
if os.path.join(path, d) not in [self._updater_path]]
|
||||
dirs[:] = [
|
||||
d for d in dirs if os.path.join(path, d) not in [self._updater_path]
|
||||
]
|
||||
for file in files:
|
||||
for pattern in self.remove_pre_update_patterns:
|
||||
if fnmatch.filter([file], pattern):
|
||||
|
@ -1066,8 +1079,9 @@ class SingletonUpdater:
|
|||
# actual file copying/replacements.
|
||||
for path, dirs, files in os.walk(merger):
|
||||
# Verify structure works to prune updater sub folder overwriting.
|
||||
dirs[:] = [d for d in dirs
|
||||
if os.path.join(path, d) not in [self._updater_path]]
|
||||
dirs[:] = [
|
||||
d for d in dirs if os.path.join(path, d) not in [self._updater_path]
|
||||
]
|
||||
rel_path = os.path.relpath(path, merger)
|
||||
dest_path = os.path.join(base, rel_path)
|
||||
if not os.path.exists(dest_path):
|
||||
|
@ -1090,23 +1104,27 @@ class SingletonUpdater:
|
|||
os.remove(dest_file)
|
||||
os.rename(srcFile, dest_file)
|
||||
self.print_verbose(
|
||||
"Overwrote file " + os.path.basename(dest_file))
|
||||
"Overwrote file " + os.path.basename(dest_file)
|
||||
)
|
||||
else:
|
||||
self.print_verbose(
|
||||
"Pattern not matched to {}, not overwritten".format(
|
||||
os.path.basename(dest_file)))
|
||||
os.path.basename(dest_file)
|
||||
)
|
||||
)
|
||||
else:
|
||||
# File did not previously exist, simply move it over.
|
||||
os.rename(srcFile, dest_file)
|
||||
self.print_verbose(
|
||||
"New file " + os.path.basename(dest_file))
|
||||
self.print_verbose("New file " + os.path.basename(dest_file))
|
||||
|
||||
# now remove the temp staging folder and downloaded zip
|
||||
try:
|
||||
shutil.rmtree(staging_path)
|
||||
except:
|
||||
error = ("Error: Failed to remove existing staging directory, "
|
||||
"consider manually removing ") + staging_path
|
||||
error = (
|
||||
"Error: Failed to remove existing staging directory, "
|
||||
"consider manually removing "
|
||||
) + staging_path
|
||||
self.print_verbose(error)
|
||||
self.print_trace()
|
||||
|
||||
|
@ -1168,12 +1186,12 @@ class SingletonUpdater:
|
|||
return ()
|
||||
|
||||
segments = list()
|
||||
tmp = ''
|
||||
tmp = ""
|
||||
for char in str(text):
|
||||
if not char.isdigit():
|
||||
if len(tmp) > 0:
|
||||
segments.append(int(tmp))
|
||||
tmp = ''
|
||||
tmp = ""
|
||||
else:
|
||||
tmp += char
|
||||
if len(tmp) > 0:
|
||||
|
@ -1184,7 +1202,7 @@ class SingletonUpdater:
|
|||
if not self._include_branches:
|
||||
return ()
|
||||
else:
|
||||
return (text)
|
||||
return text
|
||||
return tuple(segments)
|
||||
|
||||
def check_for_update_async(self, callback=None):
|
||||
|
@ -1193,7 +1211,8 @@ class SingletonUpdater:
|
|||
self._json is not None
|
||||
and "update_ready" in self._json
|
||||
and self._json["version_text"] != dict()
|
||||
and self._json["update_ready"])
|
||||
and self._json["update_ready"]
|
||||
)
|
||||
|
||||
if is_ready:
|
||||
self._update_ready = True
|
||||
|
@ -1210,15 +1229,13 @@ class SingletonUpdater:
|
|||
self.print_verbose("Skipping async check, already started")
|
||||
# already running the bg thread
|
||||
elif self._update_ready is None:
|
||||
print("{} updater: Running background check for update".format(
|
||||
self.addon))
|
||||
print("{} updater: Running background check for update".format(self.addon))
|
||||
self.start_async_check_update(False, callback)
|
||||
|
||||
def check_for_update_now(self, callback=None):
|
||||
self._error = None
|
||||
self._error_msg = None
|
||||
self.print_verbose(
|
||||
"Check update pressed, first getting current status")
|
||||
self.print_verbose("Check update pressed, first getting current status")
|
||||
if self._async_checking:
|
||||
self.print_verbose("Skipping async check, already started")
|
||||
return # already running the bg thread
|
||||
|
@ -1243,9 +1260,7 @@ class SingletonUpdater:
|
|||
# avoid running again in, just return past result if found
|
||||
# but if force now check, then still do it
|
||||
if self._update_ready is not None and not now:
|
||||
return (self._update_ready,
|
||||
self._update_version,
|
||||
self._update_link)
|
||||
return (self._update_ready, self._update_version, self._update_link)
|
||||
|
||||
if self._current_version is None:
|
||||
raise ValueError("current_version not yet defined")
|
||||
|
@ -1259,22 +1274,18 @@ class SingletonUpdater:
|
|||
self.set_updater_json() # self._json
|
||||
|
||||
if not now and not self.past_interval_timestamp():
|
||||
self.print_verbose(
|
||||
"Aborting check for updated, check interval not reached")
|
||||
self.print_verbose("Aborting check for updated, check interval not reached")
|
||||
return (False, None, None)
|
||||
|
||||
# check if using tags or releases
|
||||
# note that if called the first time, this will pull tags from online
|
||||
if self._fake_install:
|
||||
self.print_verbose(
|
||||
"fake_install = True, setting fake version as ready")
|
||||
self.print_verbose("fake_install = True, setting fake version as ready")
|
||||
self._update_ready = True
|
||||
self._update_version = "(999,999,999)"
|
||||
self._update_link = "http://127.0.0.1"
|
||||
|
||||
return (self._update_ready,
|
||||
self._update_version,
|
||||
self._update_link)
|
||||
return (self._update_ready, self._update_version, self._update_link)
|
||||
|
||||
# Primary internet call, sets self._tags and self._tag_latest.
|
||||
self.get_tags()
|
||||
|
@ -1327,7 +1338,6 @@ class SingletonUpdater:
|
|||
else:
|
||||
# Situation where branches not included.
|
||||
if new_version > self._current_version:
|
||||
|
||||
self._update_ready = True
|
||||
self._update_version = new_version
|
||||
self._update_link = link
|
||||
|
@ -1386,8 +1396,7 @@ class SingletonUpdater:
|
|||
if self._fake_install:
|
||||
# Change to True, to trigger the reload/"update installed" handler.
|
||||
self.print_verbose("fake_install=True")
|
||||
self.print_verbose(
|
||||
"Just reloading and running any handler triggers")
|
||||
self.print_verbose("Just reloading and running any handler triggers")
|
||||
self._json["just_updated"] = True
|
||||
self.save_updater_json()
|
||||
if self._backup_current is True:
|
||||
|
@ -1401,15 +1410,16 @@ class SingletonUpdater:
|
|||
self.print_verbose("Update stopped, new version not ready")
|
||||
if callback:
|
||||
callback(
|
||||
self._addon_package,
|
||||
"Update stopped, new version not ready")
|
||||
self._addon_package, "Update stopped, new version not ready"
|
||||
)
|
||||
return "Update stopped, new version not ready"
|
||||
elif self._update_link is None:
|
||||
# this shouldn't happen if update is ready
|
||||
self.print_verbose("Update stopped, update link unavailable")
|
||||
if callback:
|
||||
callback(self._addon_package,
|
||||
"Update stopped, update link unavailable")
|
||||
callback(
|
||||
self._addon_package, "Update stopped, update link unavailable"
|
||||
)
|
||||
return "Update stopped, update link unavailable"
|
||||
|
||||
if revert_tag is None:
|
||||
|
@ -1461,12 +1471,12 @@ class SingletonUpdater:
|
|||
return True
|
||||
|
||||
now = datetime.now()
|
||||
last_check = datetime.strptime(
|
||||
self._json["last_check"], "%Y-%m-%d %H:%M:%S.%f")
|
||||
last_check = datetime.strptime(self._json["last_check"], "%Y-%m-%d %H:%M:%S.%f")
|
||||
offset = timedelta(
|
||||
days=self._check_interval_days + 30 * self._check_interval_months,
|
||||
hours=self._check_interval_hours,
|
||||
minutes=self._check_interval_minutes)
|
||||
minutes=self._check_interval_minutes,
|
||||
)
|
||||
|
||||
delta = (now - offset) - last_check
|
||||
if delta.total_seconds() > 0:
|
||||
|
@ -1482,8 +1492,8 @@ class SingletonUpdater:
|
|||
Will also rename old file paths to addon-specific path if found.
|
||||
"""
|
||||
json_path = os.path.join(
|
||||
self._updater_path,
|
||||
"{}_updater_status.json".format(self._addon_package))
|
||||
self._updater_path, "{}_updater_status.json".format(self._addon_package)
|
||||
)
|
||||
old_json_path = os.path.join(self._updater_path, "updater_status.json")
|
||||
|
||||
# Rename old file if it exists.
|
||||
|
@ -1517,7 +1527,7 @@ class SingletonUpdater:
|
|||
"ignore": False,
|
||||
"just_restored": False,
|
||||
"just_updated": False,
|
||||
"version_text": dict()
|
||||
"version_text": dict(),
|
||||
}
|
||||
self.save_updater_json()
|
||||
|
||||
|
@ -1537,11 +1547,13 @@ class SingletonUpdater:
|
|||
|
||||
jpath = self.get_json_path()
|
||||
if not os.path.isdir(os.path.dirname(jpath)):
|
||||
print("State error: Directory does not exist, cannot save json: ",
|
||||
os.path.basename(jpath))
|
||||
print(
|
||||
"State error: Directory does not exist, cannot save json: ",
|
||||
os.path.basename(jpath),
|
||||
)
|
||||
return
|
||||
try:
|
||||
with open(jpath, 'w') as outf:
|
||||
with open(jpath, "w") as outf:
|
||||
data_out = json.dumps(self._json, indent=4)
|
||||
outf.write(data_out)
|
||||
except:
|
||||
|
@ -1575,8 +1587,13 @@ class SingletonUpdater:
|
|||
if self._async_checking:
|
||||
return
|
||||
self.print_verbose("Starting background checking thread")
|
||||
check_thread = threading.Thread(target=self.async_check_update,
|
||||
args=(now, callback,))
|
||||
check_thread = threading.Thread(
|
||||
target=self.async_check_update,
|
||||
args=(
|
||||
now,
|
||||
callback,
|
||||
),
|
||||
)
|
||||
check_thread.daemon = True
|
||||
self._check_thread = check_thread
|
||||
check_thread.start()
|
||||
|
@ -1630,17 +1647,19 @@ class SingletonUpdater:
|
|||
# Updater Engines
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BitbucketEngine:
|
||||
"""Integration to Bitbucket API for git-formatted repositories"""
|
||||
|
||||
def __init__(self):
|
||||
self.api_url = 'https://api.bitbucket.org'
|
||||
self.api_url = "https://api.bitbucket.org"
|
||||
self.token = None
|
||||
self.name = "bitbucket"
|
||||
|
||||
def form_repo_url(self, updater):
|
||||
return "{}/2.0/repositories/{}/{}".format(
|
||||
self.api_url, updater.user, updater.repo)
|
||||
self.api_url, updater.user, updater.repo
|
||||
)
|
||||
|
||||
def form_tags_url(self, updater):
|
||||
return self.form_repo_url(updater) + "/refs/tags?sort=-name"
|
||||
|
@ -1650,31 +1669,28 @@ class BitbucketEngine:
|
|||
|
||||
def get_zip_url(self, name, updater):
|
||||
return "https://bitbucket.org/{user}/{repo}/get/{name}.zip".format(
|
||||
user=updater.user,
|
||||
repo=updater.repo,
|
||||
name=name)
|
||||
user=updater.user, repo=updater.repo, name=name
|
||||
)
|
||||
|
||||
def parse_tags(self, response, updater):
|
||||
if response is None:
|
||||
return list()
|
||||
return [
|
||||
{
|
||||
"name": tag["name"],
|
||||
"zipball_url": self.get_zip_url(tag["name"], updater)
|
||||
} for tag in response["values"]]
|
||||
{"name": tag["name"], "zipball_url": self.get_zip_url(tag["name"], updater)}
|
||||
for tag in response["values"]
|
||||
]
|
||||
|
||||
|
||||
class GithubEngine:
|
||||
"""Integration to Github API"""
|
||||
|
||||
def __init__(self):
|
||||
self.api_url = 'https://api.github.com'
|
||||
self.api_url = "https://api.github.com"
|
||||
self.token = None
|
||||
self.name = "github"
|
||||
|
||||
def form_repo_url(self, updater):
|
||||
return "{}/repos/{}/{}".format(
|
||||
self.api_url, updater.user, updater.repo)
|
||||
return "{}/repos/{}/{}".format(self.api_url, updater.user, updater.repo)
|
||||
|
||||
def form_tags_url(self, updater):
|
||||
if updater.use_releases:
|
||||
|
@ -1698,7 +1714,7 @@ class GitlabEngine:
|
|||
"""Integration to GitLab API"""
|
||||
|
||||
def __init__(self):
|
||||
self.api_url = 'https://gitlab.com'
|
||||
self.api_url = "https://gitlab.com"
|
||||
self.token = None
|
||||
self.name = "gitlab"
|
||||
|
||||
|
@ -1710,19 +1726,19 @@ class GitlabEngine:
|
|||
|
||||
def form_branch_list_url(self, updater):
|
||||
# does not validate branch name.
|
||||
return "{}/repository/branches".format(
|
||||
self.form_repo_url(updater))
|
||||
return "{}/repository/branches".format(self.form_repo_url(updater))
|
||||
|
||||
def form_branch_url(self, branch, updater):
|
||||
# Could clash with tag names and if it does, it will download TAG zip
|
||||
# instead of branch zip to get direct path, would need.
|
||||
return "{}/repository/archive.zip?sha={}".format(
|
||||
self.form_repo_url(updater), branch)
|
||||
self.form_repo_url(updater), branch
|
||||
)
|
||||
|
||||
def get_zip_url(self, sha, updater):
|
||||
return "{base}/repository/archive.zip?sha={sha}".format(
|
||||
base=self.form_repo_url(updater),
|
||||
sha=sha)
|
||||
base=self.form_repo_url(updater), sha=sha
|
||||
)
|
||||
|
||||
# def get_commit_zip(self, id, updater):
|
||||
# return self.form_repo_url(updater)+"/repository/archive.zip?sha:"+id
|
||||
|
@ -1733,8 +1749,11 @@ class GitlabEngine:
|
|||
return [
|
||||
{
|
||||
"name": tag["name"],
|
||||
"zipball_url": self.get_zip_url(tag["commit"]["id"], updater)
|
||||
} for tag in response]
|
||||
"zipball_url": self.get_zip_url(tag["commit"]["id"], updater),
|
||||
}
|
||||
for tag in response
|
||||
]
|
||||
|
||||
|
||||
class ForgejoEngine:
|
||||
"""Integration to Forgejo/Gitea API"""
|
||||
|
@ -1742,7 +1761,7 @@ class ForgejoEngine:
|
|||
def __init__(self):
|
||||
# the api_url may be overwritten by form_repo_url
|
||||
# if updater.host is set
|
||||
self.api_url = 'https://codeberg.org'
|
||||
self.api_url = "https://codeberg.org"
|
||||
self.token = None
|
||||
self.name = "forgejo"
|
||||
|
||||
|
@ -1756,19 +1775,17 @@ class ForgejoEngine:
|
|||
|
||||
def form_branch_list_url(self, updater):
|
||||
# does not validate branch name.
|
||||
return "{}/branches".format(
|
||||
self.form_repo_url(updater))
|
||||
return "{}/branches".format(self.form_repo_url(updater))
|
||||
|
||||
def form_branch_url(self, branch, updater):
|
||||
# Could clash with tag names and if it does, it will download TAG zip
|
||||
# instead of branch zip to get direct path, would need.
|
||||
return "{}/archive/{}.zip".format(
|
||||
self.form_repo_url(updater), branch)
|
||||
return "{}/archive/{}.zip".format(self.form_repo_url(updater), branch)
|
||||
|
||||
def get_zip_url(self, sha, updater):
|
||||
return "{base}/archive/{sha}.zip".format(
|
||||
base=self.form_repo_url(updater),
|
||||
sha=sha)
|
||||
base=self.form_repo_url(updater), sha=sha
|
||||
)
|
||||
|
||||
# def get_commit_zip(self, id, updater):
|
||||
# return self.form_repo_url(updater)+"/repository/archive.zip?sha:"+id
|
||||
|
@ -1779,8 +1796,11 @@ class ForgejoEngine:
|
|||
return [
|
||||
{
|
||||
"name": tag["name"],
|
||||
"zipball_url": self.get_zip_url(tag["commit"]["sha"], updater)
|
||||
} for tag in response]
|
||||
"zipball_url": self.get_zip_url(tag["commit"]["sha"], updater),
|
||||
}
|
||||
for tag in response
|
||||
]
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The module-shared class instance,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue