Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --update option #693

Merged
merged 5 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion umake/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def main():
add_help=False)
parser.add_argument('--help', action=_HelpAction, help=_('Show this help')) # add custom help
parser.add_argument("-v", "--verbose", action="count", default=0, help=_("Increase output verbosity (2 levels)"))

parser.add_argument('-u', '--update', action='store_true', help=_('Update installed frameworks'))
parser.add_argument('-r', '--remove', action="store_true", help=_("Remove specified framework if installed"))

list_group = parser.add_argument_group("List frameworks").add_mutually_exclusive_group()
Expand Down
17 changes: 16 additions & 1 deletion umake/frameworks/android.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


"""Android module"""

import json
from contextlib import suppress
from gettext import gettext as _
import logging
Expand Down Expand Up @@ -108,6 +108,21 @@ def post_install(self):
categories="Development;IDE;",
extra="StartupWMClass=jetbrains-studio"))

def parse_latest_version_from_package_url(self):
return (re.search(r'(\d+\.\d+)', self.package_url).group(1)
if self.package_url else 'Missing information')

@staticmethod
def get_current_user_version(install_path):
try:
with open(os.path.join(install_path, 'product-info.json'), 'r') as file:
data = json.load(file)
version_not_formatted = data.get('dataDirectoryName', 'Missing information')
match = re.search(r'\d+\.\d+', version_not_formatted)
return match.group() if match else 'Missing information'
except FileNotFoundError:
return 'Missing information'


class AndroidSDK(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down
127 changes: 74 additions & 53 deletions umake/frameworks/baseinstaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def __init__(self, *args, **kwargs):
"""The Downloader framework isn't instantiated directly, but is useful to inherit from for all frameworks

having a set of downloads to proceed, some eventual supported_archs."""
self.package_url = None
self.download_page = kwargs["download_page"]
self.checksum_type = kwargs.get("checksum_type", None)
self.dir_to_decompress_in_tarball = kwargs.get("dir_to_decompress_in_tarball", "")
Expand Down Expand Up @@ -211,6 +212,78 @@ def parse_download_link(self, line, in_download):
((url, md5sum), in_download=True/False)"""
pass

def store_package_url(self, result):
logger.debug("Parse download metadata")
self.auto_accept_license = True
self.dry_run = True

error_msg = result[self.download_page].error
if error_msg:
logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg))

self.new_download_url = None
self.shasum_read_method = hasattr(self, 'get_sha_and_start_download')
with StringIO() as license_txt:
url, checksum = self.get_metadata(result, license_txt)
self.package_url = url

def get_metadata(self, result, license_txt):

url, checksum = (None, None)
page = result[self.download_page]
if self.json is True:
logger.debug("Using json parser")
try:
latest = json.loads(page.buffer.read().decode())
# On a download from github, if the page is not .../releases/latest
# we want to download the latest version (beta/development)
# So we get the first element in the json tree.
# In the framework we only change the url and this condition is satisfied.
if self.download_page.startswith("https://api.github.com") and \
not self.download_page.endswith("/latest"):
latest = latest[0]
url = None
in_download = False
(url, in_download) = self.parse_download_link(latest, in_download)
if not url:
if not self.url:
raise IndexError
else:
logger.debug("We set a temporary url while fetching the checksum")
url = self.url
except (json.JSONDecodeError, IndexError):
logger.error("Can't parse the download URL from the download page.")
UI.return_main_screen(status_code=1)
logger.debug("Found download URL: " + url)

else:
in_license = False
in_download = False
for line in page.buffer:
line_content = line.decode()

if self.expect_license and not self.auto_accept_license:
in_license = self.parse_license(line_content, license_txt, in_license)

# always take the first valid (url, checksum) if not match_last_link is set to True:
download = None
# if not in_download:
if (url is None or (self.checksum_type and not checksum) or
self.match_last_link) and \
not (self.shasum_read_method and self.new_download_url):
(download, in_download) = self.parse_download_link(line_content, in_download)

if download is not None:
(newurl, new_checksum) = download
url = newurl if newurl is not None else url
checksum = new_checksum if new_checksum is not None else checksum
if url is not None:
if self.checksum_type and checksum:
logger.debug("Found download link for {}, checksum: {}".format(url, checksum))
elif not self.checksum_type:
logger.debug("Found download link for {}".format(url))
return url, checksum

@MainLoop.in_mainloop_thread
def get_metadata_and_check_license(self, result):
"""Download files to download + license and check it"""
Expand All @@ -224,59 +297,7 @@ def get_metadata_and_check_license(self, result):
self.new_download_url = None
self.shasum_read_method = hasattr(self, 'get_sha_and_start_download')
with StringIO() as license_txt:
url, checksum = (None, None)
page = result[self.download_page]
if self.json is True:
logger.debug("Using json parser")
try:
latest = json.loads(page.buffer.read().decode())
# On a download from github, if the page is not .../releases/latest
# we want to download the latest version (beta/development)
# So we get the first element in the json tree.
# In the framework we only change the url and this condition is satisfied.
if self.download_page.startswith("https://api.github.com") and\
not self.download_page.endswith("/latest"):
latest = latest[0]
url = None
in_download = False
(url, in_download) = self.parse_download_link(latest, in_download)
if not url:
if not self.url:
raise IndexError
else:
logger.debug("We set a temporary url while fetching the checksum")
url = self.url
except (json.JSONDecodeError, IndexError):
logger.error("Can't parse the download URL from the download page.")
UI.return_main_screen(status_code=1)
logger.debug("Found download URL: " + url)

else:
in_license = False
in_download = False
for line in page.buffer:
line_content = line.decode()

if self.expect_license and not self.auto_accept_license:
in_license = self.parse_license(line_content, license_txt, in_license)

# always take the first valid (url, checksum) if not match_last_link is set to True:
download = None
# if not in_download:
if (url is None or (self.checksum_type and not checksum) or
self.match_last_link) and\
not(self.shasum_read_method and self.new_download_url):
(download, in_download) = self.parse_download_link(line_content, in_download)
if download is not None:
(newurl, new_checksum) = download
url = newurl if newurl is not None else url
checksum = new_checksum if new_checksum is not None else checksum
if url is not None:
if self.checksum_type and checksum:
logger.debug("Found download link for {}, checksum: {}".format(url, checksum))
elif not self.checksum_type:
logger.debug("Found download link for {}".format(url))

url, checksum = self.get_metadata(result, license_txt)
if hasattr(self, 'get_sha_and_start_download'):
logger.debug('Run get_sha_and_start_download')
DownloadCenter(urls=[DownloadItem(self.new_download_url, None)],
Expand Down
7 changes: 7 additions & 0 deletions umake/frameworks/crystal.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,10 @@ def post_install(self):
"""Add Crystal necessary env variables"""
add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")}})
UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name)))

def parse_latest_version_from_package_url(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially you can remove these empty methods, and add them to baseinstaller/init
so the single frameworks only override this if they can

return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'
12 changes: 12 additions & 0 deletions umake/frameworks/dart.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ def post_install(self):
add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")}})
UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name)))

def parse_latest_version_from_package_url(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are fine, since they add what is specific to a package, although they could simply return the regex string, and let a method in baseinstaller deal with evaluating the regex

return (re.search(r'/(\d+\.\d+\.\d+)', self.package_url).group(1)
if self.package_url else 'Missing information')

@staticmethod
def get_current_user_version(install_path):
try:
with open(os.path.join(install_path, 'version'), 'r') as file:
return file.readline().strip() if file else 'Missing information'
except FileNotFoundError:
return 'Missing information'


class FlutterLang(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down
18 changes: 17 additions & 1 deletion umake/frameworks/devops.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@


"""Devops module"""

import re
import subprocess
from gettext import gettext as _
import logging
import os
Expand Down Expand Up @@ -67,3 +68,18 @@ def post_install(self):
"""Add Terraform necessary env variables"""
add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path)}})
UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name)))

def parse_latest_version_from_package_url(self):
return (re.search(r'/(\d+\.\d+\.\d+)', self.package_url).group(1)
if self.package_url else 'Missing information')

@staticmethod
def get_current_user_version(install_path):
file = os.path.join(install_path, 'terraform')
command = f"{file} --version"
try:
result = subprocess.check_output(command, shell=True, text=True)
match = re.search(r'Terraform\s+v(\d+\.\d+\.\d+)', result)
return match.group(1) if match else 'Missing information'
except subprocess.CalledProcessError as e:
return 'Missing information'
27 changes: 27 additions & 0 deletions umake/frameworks/electronics.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ def post_install(self):
UI.return_main_screen(status_code=1)
UI.delayed_display(DisplayMessage(_("You need to logout and login again for your installation to work")))

def parse_latest_version_from_package_url(self):
return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'




class ArduinoLegacy(umake.frameworks.baseinstaller.BaseInstaller):
Expand Down Expand Up @@ -175,6 +183,13 @@ def post_install(self):
UI.return_main_screen(status_code=1)
UI.delayed_display(DisplayMessage(_("You need to logout and login again for your installation to work")))

def parse_latest_version_from_package_url(self):
return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'


class Eagle(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down Expand Up @@ -205,6 +220,18 @@ def post_install(self):
comment=self.description,
categories="Development;"))

def parse_latest_version_from_package_url(self):
return re.search(r'/(\d+(?:_\d+)*)/', self.package_url).group(1). \
replace('_', '.') if self.package_url else 'Missing information'

@staticmethod
def get_current_user_version(install_path):
try:
with open(os.path.join(install_path, 'bin', 'eagle.def'), 'r') as file:
return re.search(r'(\d+(\.\d+)+)', next(file)).group(1) if file else 'Missing information'
except FileNotFoundError:
return 'Missing information'


class Fritzing(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down
33 changes: 33 additions & 0 deletions umake/frameworks/games.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ def post_install(self):
comment=self.description,
categories="Development;IDE;Graphics"))

def parse_latest_version_from_package_url(self):
return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'


class Unity3D(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down Expand Up @@ -133,6 +140,13 @@ def save_icon(self, download_result):
shutil.copy(icon, os.path.join(self.install_path, self.icon_name))
logger.debug("Copied icon: {}".format(self.icon_url))

def parse_latest_version_from_package_url(self):
return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'


class Superpowers(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down Expand Up @@ -168,6 +182,18 @@ def post_install(self):
comment=self.description,
categories="Development;IDE;"))

def parse_latest_version_from_package_url(self):
return (re.search(r'/v(\d+\.\d+\.\d+)', self.package_url).group(1)
if self.package_url else 'Missing information')

@staticmethod
def get_current_user_version(install_path):
try:
with open(os.path.join(install_path, 'version'), 'r') as file:
return file.readline().strip() if file else 'Missing information'
except FileNotFoundError:
return 'Missing information'


class GDevelop(umake.frameworks.baseinstaller.BaseInstaller):

Expand Down Expand Up @@ -229,3 +255,10 @@ def save_icon(self, download_result):
icon = download_result.pop(self.icon_url).fd.name
shutil.copy(icon, os.path.join(self.install_path, self.icon_filename))
logger.debug("Copied icon: {}".format(self.icon_url))

def parse_latest_version_from_package_url(self):
return 'Missing information'

@staticmethod
def get_current_user_version(install_path):
return 'Missing information'
12 changes: 12 additions & 0 deletions umake/frameworks/go.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,15 @@ def post_install(self):
add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")},
"GOROOT": {"value": self.install_path, "keep": False}})
UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name)))

def parse_latest_version_from_package_url(self):
return (re.search(r'go(\d+(\.\d+)+)', self.package_url).group(1)
if self.package_url else 'Missing information')

@staticmethod
def get_current_user_version(install_path):
try:
with open(os.path.join(install_path, 'VERSION'), 'r') as file:
return re.search(r'go(\d+(\.\d+)+)', next(file)).group(1) if file else 'Missing information'
except FileNotFoundError:
return 'Missing information'
Loading