#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
**BETTERSIS.UPDATE_CHECKER**:
contains function that help BetterSIS to check for updates
"""
__author__ = "Zenaro Stefano"
import os
import subprocess
import logging
import urllib.request
import json
import ssl
import certifi
try:
from ._version import __version__ # noqa: F401
except ImportError:
from _version import __version__ # noqa: F401
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
ghreleases_apiurl = "https://api.github.com/repos/mario33881/bettersis/releases"
[docs]def get_old_versions(t_ghreleases_apiurl):
"""
Returns a list of old versions.
First the function collects all the releases in a list and then
removes the latest release from the list.
:param str t_ghreleases_apiurl: api url for gh releases
:return list versions: old versions
"""
with urllib.request.urlopen(
t_ghreleases_apiurl,
context=ssl.create_default_context(cafile=certifi.where())
) as url:
releases_data = json.loads(url.read().decode())
versions = []
for data in releases_data:
if "tag_name" in data.keys():
versions.append(data["tag_name"])
with urllib.request.urlopen(
t_ghreleases_apiurl + "/latest",
context=ssl.create_default_context(cafile=certifi.where())
) as url:
latest_release_data = json.loads(url.read().decode())
if "tag_name" in latest_release_data.keys():
versions.remove(latest_release_data["tag_name"])
return versions
[docs]def check_updates(t_ghreleases_apiurl, t_version): # noqa: C901
"""
Checks for updates.
:param str t_version: current version
:param str t_ghreleases_apiurl: api url for gh releases
:return dict res: dictionary with success status, errors, update_version, update_available
"""
res = {"success": False, "errors": [], "latest_version": None, "update_available": False}
try:
current_version = extract_version(t_version)
if current_version["success"]:
# Get Github Releases information
with urllib.request.urlopen(
t_ghreleases_apiurl + "/latest",
context=ssl.create_default_context(cafile=certifi.where())
) as url:
latest_release_data = json.loads(url.read().decode())
if "tag_name" in latest_release_data.keys():
tag_name = latest_release_data["tag_name"]
logger.debug("Found latest release version: " + tag_name)
res["latest_version"] = tag_name
latest_version_data = extract_version(tag_name)
if latest_version_data["success"]:
res["success"] = True
# if one of the "ifs" is true, the currently running version is not the latest version
if latest_version_data["major_version"] > current_version["major_version"]:
res["update_available"] = True
elif latest_version_data["major_version"] == current_version["major_version"]:
if latest_version_data["minor_version"] > current_version["minor_version"]:
res["update_available"] = True
elif latest_version_data["minor_version"] == current_version["minor_version"]:
if latest_version_data["patch_version"] > current_version["patch_version"]:
res["update_available"] = True
else:
e = "[CHECK_UPDATES] Couldn't parse the latest version string '{}'".format(tag_name)
logger.error(e)
res["errors"].append(e)
else:
e = "[CHECK_UPDATES] Couldn't parse the current version string '{}'".format(t_version)
logger.error(e)
res["errors"].append(e)
except Exception as e:
logger.error("[CHECK_UPDATES] Error during update check: ", exc_info=True, stack_info=True)
res["errors"].append(e)
if res["update_available"]:
logger.debug("[CHECK_UPDATES] Checked updates: latest version found"
" is version {}, update available? {}".format(res["latest_version"], res["update_available"]))
return res
[docs]def update_appimage(): # noqa: C901
"""
If this function was run in an appimage and there are updates,
download the latest AppImage and ask the user if they want to
delete old versions (if present).
:return bool success: True if the check for updates was successful
"""
success = False
update_info = check_updates(ghreleases_apiurl, __version__.split(" ")[1])
try:
if "APPIMAGE" in os.environ and "APPDIR" in os.environ:
if update_info["success"]:
if update_info["update_available"]:
aiut_path = os.path.join(os.environ["APPDIR"], "appimageupdate", "AppRun")
subprocess.call([aiut_path, os.environ["APPIMAGE"]])
else:
print("Already using latest version. No new updates found.")
success = True
found_old_version = False
wants_delete = False
for version in get_old_versions(ghreleases_apiurl):
version_path = os.path.join(os.environ["APPDIR"], "BetterSIS-" + version + "-x86_64.AppImage")
if os.path.isfile(version_path) or os.path.isfile(version_path + ".zs-old"):
if not found_old_version:
found_old_version = True
user_input = ""
while user_input not in ["y", "n"]:
user_input = input("Found an/many old AppImage(s): do you want to delete it? [y/n]: ")
user_input.strip().lower()
if user_input == "y":
wants_delete = True
if wants_delete and os.path.isfile(version_path):
os.remove(version_path)
if wants_delete and os.path.isfile(version_path + ".zs-old"):
os.remove(version_path + ".zs-old")
else:
print("Couldn't get releases data")
else:
print("Can't check for updates: it looks like you are not running the AppImage version")
except Exception as e:
print("Something went wrong during the update:", e)
return success
if __name__ == "__main__":
import pprint
print("This is a simple test for this module:")
updates = check_updates(ghreleases_apiurl, "0.0.0")
print("Update found: ")
pprint.pprint(updates)
noupdates = check_updates(ghreleases_apiurl, "999.999.999")
print("\nNo Update found: ")
pprint.pprint(noupdates)
print("\nOld versions:")
pprint.pprint(get_old_versions(ghreleases_apiurl))