125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
import re
|
|
import sublime
|
|
|
|
from ..versions import version_sort, version_exclude_prerelease
|
|
|
|
|
|
class ReleaseSelector():
|
|
"""
|
|
A base class for finding the best version of a package for the current machine
|
|
"""
|
|
|
|
def select_release(self, package_info):
|
|
"""
|
|
Returns a modified package info dict for package from package schema version 2.0
|
|
|
|
:param package_info:
|
|
A package info dict with a "releases" key
|
|
|
|
:return:
|
|
The package info dict with the "releases" key deleted, and a
|
|
"download" key added that contains a dict with "version", "url" and
|
|
"date" keys.
|
|
None if no compatible relases are available.
|
|
"""
|
|
|
|
releases = version_sort(package_info['releases'])
|
|
if not self.settings.get('install_prereleases'):
|
|
releases = version_exclude_prerelease(releases)
|
|
|
|
for release in releases:
|
|
platforms = release.get('platforms', '*')
|
|
if not isinstance(platforms, list):
|
|
platforms = [platforms]
|
|
|
|
best_platform = self.get_best_platform(platforms)
|
|
if not best_platform:
|
|
continue
|
|
|
|
if not self.is_compatible_version(release.get('sublime_text', '<3000')):
|
|
continue
|
|
|
|
package_info['download'] = release
|
|
package_info['last_modified'] = release.get('date')
|
|
del package_info['releases']
|
|
|
|
return package_info
|
|
|
|
return None
|
|
|
|
def select_platform(self, package_info):
|
|
"""
|
|
Returns a modified package info dict for package from package schema version <= 1.2
|
|
|
|
:param package_info:
|
|
A package info dict with a "platforms" key
|
|
|
|
:return:
|
|
The package info dict with the "platforms" key deleted, and a
|
|
"download" key added that contains a dict with "version" and "url"
|
|
keys.
|
|
None if no compatible platforms.
|
|
"""
|
|
platforms = list(package_info['platforms'].keys())
|
|
best_platform = self.get_best_platform(platforms)
|
|
if not best_platform:
|
|
return None
|
|
|
|
package_info['download'] = package_info['platforms'][best_platform][0]
|
|
package_info['download']['date'] = package_info.get('last_modified')
|
|
del package_info['platforms']
|
|
|
|
return package_info
|
|
|
|
def get_best_platform(self, platforms):
|
|
"""
|
|
Returns the most specific platform that matches the current machine
|
|
|
|
:param platforms:
|
|
An array of platform names for a package. E.g. ['*', 'windows', 'linux-x64']
|
|
|
|
:return: A string reprenting the most specific matching platform
|
|
"""
|
|
|
|
ids = [sublime.platform() + '-' + sublime.arch(), sublime.platform(),
|
|
'*']
|
|
|
|
for id in ids:
|
|
if id in platforms:
|
|
return id
|
|
|
|
return None
|
|
|
|
def is_compatible_version(self, version_range):
|
|
min_version = float("-inf")
|
|
max_version = float("inf")
|
|
|
|
if version_range == '*':
|
|
return True
|
|
|
|
gt_match = re.match('>(\d+)$', version_range)
|
|
ge_match = re.match('>=(\d+)$', version_range)
|
|
lt_match = re.match('<(\d+)$', version_range)
|
|
le_match = re.match('<=(\d+)$', version_range)
|
|
range_match = re.match('(\d+) - (\d+)$', version_range)
|
|
|
|
if gt_match:
|
|
min_version = int(gt_match.group(1)) + 1
|
|
elif ge_match:
|
|
min_version = int(ge_match.group(1))
|
|
elif lt_match:
|
|
max_version = int(lt_match.group(1)) - 1
|
|
elif le_match:
|
|
max_version = int(le_match.group(1))
|
|
elif range_match:
|
|
min_version = int(range_match.group(1))
|
|
max_version = int(range_match.group(2))
|
|
else:
|
|
return None
|
|
|
|
if min_version > int(sublime.version()):
|
|
return False
|
|
if max_version < int(sublime.version()):
|
|
return False
|
|
|
|
return True
|