Improve support for partial package versions

This commit is contained in:
Ivan Kravets
2017-12-27 19:37:26 +02:00
parent 55d4fc23d0
commit ad08ed8d12
3 changed files with 52 additions and 45 deletions

View File

@ -21,7 +21,6 @@ from os.path import isdir, join
import arrow
import click
import semantic_version
from platformio import app, commands, exception, util
from platformio.managers.package import BasePkgManager
@ -153,8 +152,7 @@ class LibraryManager(BasePkgManager):
]
return items
@staticmethod
def max_satisfying_repo_version(versions, requirements=None):
def max_satisfying_repo_version(self, versions, requirements=None):
def _cmp_dates(datestr1, datestr2):
date1 = arrow.get(datestr1)
@ -163,29 +161,22 @@ class LibraryManager(BasePkgManager):
return 0
return -1 if date1 < date2 else 1
semver_spec = self.parse_semver_spec(
requirements) if requirements else None
item = None
reqspec = None
if requirements:
try:
reqspec = semantic_version.Spec(requirements)
except ValueError:
pass
for v in versions:
specver = None
try:
specver = semantic_version.Version(v['name'], partial=True)
except ValueError:
pass
if reqspec:
if not specver or specver not in reqspec:
for v in versions:
semver_new = self.parse_semver_version(v['name'])
if semver_spec:
if not semver_new or semver_new not in semver_spec:
continue
if not item or semantic_version.Version(
item['name'], partial=True) < specver:
if not item or self.parse_semver_version(
item['name']) < semver_new:
item = v
elif requirements:
if requirements == v['name']:
return v
else:
if not item or _cmp_dates(item['released'],
v['released']) == -1:

View File

@ -191,6 +191,27 @@ class PkgInstallerMixin(object):
with FileUnpacker(source_path) as fu:
return fu.unpack(dest_dir)
@staticmethod
def parse_semver_spec(value, raise_exception=False):
try:
return semantic_version.Spec(value)
except ValueError as e:
if raise_exception:
raise e
return None
@staticmethod
def parse_semver_version(value, raise_exception=False):
try:
try:
return semantic_version.Version(value)
except ValueError:
return semantic_version.Version.coerce(value)
except ValueError as e:
if raise_exception:
raise e
return None
@staticmethod
def get_install_dirname(manifest):
name = re.sub(r"[^\da-z\_\-\. ]", "_", manifest['name'], flags=re.I)
@ -290,15 +311,15 @@ class PkgInstallerMixin(object):
return manifest
try:
if requirements and not semantic_version.Spec(
requirements).match(
semantic_version.Version(
manifest['version'], partial=True)):
if requirements and not self.parse_semver_spec(
requirements, raise_exception=True).match(
self.parse_semver_version(
manifest['version'], raise_exception=True)):
continue
elif not best or (semantic_version.Version(
manifest['version'], partial=True) >
semantic_version.Version(
best['version'], partial=True)):
elif not best or (self.parse_semver_version(
manifest['version'], raise_exception=True) >
self.parse_semver_version(
best['version'], raise_exception=True)):
best = manifest
except ValueError:
pass
@ -406,16 +427,10 @@ class PkgInstallerMixin(object):
pkg_dir = join(self.package_dir, pkg_dirname)
cur_manifest = self.load_manifest(pkg_dir)
tmp_semver = None
tmp_semver = self.parse_semver_version(tmp_manifest['version'])
cur_semver = None
try:
tmp_semver = semantic_version.Version(
tmp_manifest['version'], partial=True)
if cur_manifest:
cur_semver = semantic_version.Version(
cur_manifest['version'], partial=True)
except ValueError:
pass
if cur_manifest:
cur_semver = self.parse_semver_version(cur_manifest['version'])
# package should satisfy requirements
if requirements:
@ -591,8 +606,10 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
up_to_date = False
try:
assert "__src_url" not in manifest
up_to_date = (semantic_version.Version.coerce(manifest['version'])
>= semantic_version.Version.coerce(latest))
up_to_date = (self.parse_semver_version(
manifest['version'], raise_exception=True) >=
self.parse_semver_version(
latest, raise_exception=True))
except (AssertionError, ValueError):
up_to_date = latest == manifest['version']

View File

@ -156,7 +156,7 @@ def test_install_packages(isolated_pio_home, tmpdir):
dict(id=1, name="name_1", version="shasum"),
dict(id=1, name="name_1", version="2.0.0"),
dict(id=1, name="name_1", version="2.1.0"),
dict(id=1, name="name_1", version="1.2.0"),
dict(id=1, name="name_1", version="1.2"),
dict(id=1, name="name_1", version="1.0.0"),
dict(name="name_2", version="1.0.0"),
dict(name="name_2", version="2.0.0",
@ -177,7 +177,7 @@ def test_install_packages(isolated_pio_home, tmpdir):
assert len(pm.get_installed()) == len(packages) - 1
pkg_dirnames = [
'name_1_ID1', 'name_1_ID1@1.0.0', 'name_1_ID1@1.2.0',
'name_1_ID1', 'name_1_ID1@1.0.0', 'name_1_ID1@1.2',
'name_1_ID1@2.0.0', 'name_1_ID1@shasum', 'name_2',
'name_2@src-177cbce1f0705580d17790fda1cc2ef5',
'name_2@src-f863b537ab00f4c7b5011fc44b120e1f'
@ -192,12 +192,11 @@ def test_get_package(isolated_pio_home):
[("1", ), None],
[("id=1", "shasum"), dict(id=1, name="name_1", version="shasum")],
[("id=1", "*"), dict(id=1, name="name_1", version="2.1.0")],
[("id=1", "^1"), dict(id=1, name="name_1", version="1.2.0")],
[("id=1", "^1"), dict(id=1, name="name_1", version="1.2.0")],
[("name_1", "<2"), dict(id=1, name="name_1", version="1.2.0")],
[("id=1", "^1"), dict(id=1, name="name_1", version="1.2")],
[("id=1", "^1"), dict(id=1, name="name_1", version="1.2")],
[("name_1", "<2"), dict(id=1, name="name_1", version="1.2")],
[("name_1", ">2"), None],
[("name_1", "2-0-0"), dict(id=1, name="name_1", version="2.1.0")],
[("name_1", "2-0-0"), dict(id=1, name="name_1", version="2.1.0")],
[("name_1", "2-0-0"), None],
[("name_2", ), dict(name="name_2", version="4.0.0")],
[("url_has_higher_priority", None, "git+https://github.com"),
dict(name="name_2", version="2.0.0",