Improve support for VCS packages

This commit is contained in:
Ivan Kravets
2017-11-25 00:31:16 +02:00
parent d07833e010
commit 53b37216cc
7 changed files with 84 additions and 91 deletions

2
docs

Submodule docs updated: ea486d6022...0efb6ee60c

View File

@ -128,7 +128,7 @@ def lib_update(lm, libraries, only_check, json_output):
requirements = None
url = None
if not pkg_dir:
name, requirements, url = lm.parse_pkg_input(library)
name, requirements, url = lm.parse_pkg_uri(library)
pkg_dir = lm.get_package_dir(name, requirements, url)
if not pkg_dir:
continue
@ -314,7 +314,7 @@ def lib_builtin(storage, json_output):
@click.option("--json-output", is_flag=True)
def lib_show(library, json_output):
lm = LibraryManager()
name, requirements, _ = lm.parse_pkg_input(library)
name, requirements, _ = lm.parse_pkg_uri(library)
lib_id = lm.get_pkg_id_by_name(
name, requirements, silent=json_output, interactive=not json_output)
lib = get_api_result("/lib/info/%d" % lib_id, cache_valid="1d")

View File

@ -351,7 +351,7 @@ def platform_update(platforms, only_packages, only_check, json_output):
requirements = None
url = None
if not pkg_dir:
name, requirements, url = pm.parse_pkg_input(platform)
name, requirements, url = pm.parse_pkg_uri(platform)
pkg_dir = pm.get_package_dir(name, requirements, url)
if not pkg_dir:
continue

View File

@ -242,8 +242,7 @@ class LibraryManager(BasePkgManager):
interactive=False):
pkg_dir = None
try:
_name, _requirements, _url = self.parse_pkg_input(
name, requirements)
_name, _requirements, _url = self.parse_pkg_uri(name, requirements)
if not _url:
name = "id=%d" % self.get_pkg_id_by_name(
_name,

View File

@ -490,51 +490,59 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl)
@staticmethod
def parse_pkg_input( # pylint: disable=too-many-branches
def parse_pkg_uri( # pylint: disable=too-many-branches
text, requirements=None):
text = str(text)
# git@github.com:user/package.git
url_marker = text[:4]
if url_marker not in ("git@", "git+") or ":" not in text:
url_marker = "://"
name, url = None, None
# Parse requirements
req_conditions = [
"@" in text,
not requirements,
not url_marker.startswith("git")
] # yapf: disable
"@" in text, not requirements, "://" not in text
or text.rfind("/") < text.rfind("@")
]
if all(req_conditions):
text, requirements = text.rsplit("@", 1)
# Handle PIO Library Registry ID
if text.isdigit():
text = "id=" + text
# Parse custom name
elif "=" in text and not text.startswith("id="):
name, text = text.split("=", 1)
name, url = (None, text)
if "=" in text and not text.startswith("id="):
name, url = text.split("=", 1)
# Parse URL
# if valid URL with scheme vcs+protocol://
if "+" in text and text.find("+") < text.find("://"):
url = text
elif "/" in text or "\\" in text:
git_conditions = [
# Handle GitHub URL (https://github.com/user/package)
text.startswith("https://github.com/") and not text.endswith(
(".zip", ".tar.gz")),
text.startswith("http")
and (text.split("#", 1)[0]
if "#" in text else text).endswith(".git")
]
hg_conditions = [
# Handle Developer Mbed URL
# (https://developer.mbed.org/users/user/code/package/)
text.startswith("https://developer.mbed.org")
]
if any(git_conditions):
url = "git+" + text
elif any(hg_conditions):
url = "hg+" + text
elif "://" not in text and (isfile(text) or isdir(text)):
url = "file://" + text
elif "://" in text:
url = text
git_conditions = [
# Handle GitHub URL (https://github.com/user/package)
url.startswith("https://github.com/") and not url.endswith(
(".zip", ".tar.gz")),
url.startswith("http")
and (url.split("#", 1)[0] if "#" in url else url).endswith(".git")
]
if any(git_conditions):
url = "git+" + url
# Handle short version of GitHub URL
if text.count("/") == 1:
url = "git+https://github.com/" + text
# Handle Developer Mbed URL
# (https://developer.mbed.org/users/user/code/package/)
if url.startswith("https://developer.mbed.org"):
url = "hg+" + url
if any([s in url for s in ("\\", "/")]) and url_marker not in url:
if isfile(url) or isdir(url):
url = "file://" + url
elif url.count("/") == 1 and "git" not in url_marker:
url = "git+https://github.com/" + url
# determine name
if url_marker in url and not name:
# Parse name from URL
if url and not name:
_url = url.split("#", 1)[0] if "#" in url else url
if _url.endswith(("\\", "/")):
_url = _url[:-1]
@ -542,8 +550,6 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
if "." in name and not name.startswith("."):
name = name.rsplit(".", 1)[0]
if url_marker not in url:
url = None
return (name or text, requirements, url)
def outdated(self, pkg_dir, requirements=None):
@ -607,7 +613,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
return
self.INSTALL_HISTORY.append(history_key)
name, requirements, url = self.parse_pkg_input(name, requirements)
name, requirements, url = self.parse_pkg_uri(name, requirements)
package_dir = self.get_package_dir(name, requirements, url)
if not package_dir or not silent:
@ -653,8 +659,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
if isdir(package):
pkg_dir = package
else:
name, requirements, url = self.parse_pkg_input(
package, requirements)
name, requirements, url = self.parse_pkg_uri(package, requirements)
pkg_dir = self.get_package_dir(name, requirements, url)
if not pkg_dir:
@ -694,7 +699,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
if isdir(package):
pkg_dir = package
else:
pkg_dir = self.get_package_dir(*self.parse_pkg_input(package))
pkg_dir = self.get_package_dir(*self.parse_pkg_uri(package))
if not pkg_dir:
raise exception.UnknownPackage("%s @ %s" % (package,

View File

@ -84,8 +84,7 @@ class PlatformManager(BasePkgManager):
if isdir(package):
pkg_dir = package
else:
name, requirements, url = self.parse_pkg_input(
package, requirements)
name, requirements, url = self.parse_pkg_uri(package, requirements)
pkg_dir = self.get_package_dir(name, requirements, url)
p = PlatformFactory.newPlatform(pkg_dir)
@ -108,8 +107,7 @@ class PlatformManager(BasePkgManager):
if isdir(package):
pkg_dir = package
else:
name, requirements, url = self.parse_pkg_input(
package, requirements)
name, requirements, url = self.parse_pkg_uri(package, requirements)
pkg_dir = self.get_package_dir(name, requirements, url)
p = PlatformFactory.newPlatform(pkg_dir)
@ -219,7 +217,7 @@ class PlatformFactory(object):
platform_dir = dirname(name)
name = util.load_json(name)['name']
else:
name, requirements, url = pm.parse_pkg_input(name, requirements)
name, requirements, url = pm.parse_pkg_uri(name, requirements)
platform_dir = pm.get_package_dir(name, requirements, url)
if platform_dir:
name = pm.load_manifest(platform_dir)['name']
@ -263,16 +261,10 @@ class PlatformPackagesMixin(object):
continue
elif (name in with_packages or
not (skip_default_package or opts.get("optional", False))):
if self.is_valid_requirements(version):
self.pm.install(name, version, silent=silent)
elif version.startswith("git@"):
self.pm.install(version, silent=silent)
if "://" in version:
self.pm.install("%s=%s" % (name, version), silent=silent)
else:
requirements = None
if "@" in version:
version, requirements = version.rsplit("@", 1)
self.pm.install(
"%s=%s" % (name, version), requirements, silent=silent)
self.pm.install(name, version, silent=silent)
return True
@ -295,10 +287,10 @@ class PlatformPackagesMixin(object):
def update_packages(self, only_check=False):
for name, manifest in self.get_installed_packages().items():
version = self.packages[name].get("version", "")
if "@" in version and not version.startswith("git@"):
_, version = version.rsplit("@", 1)
self.pm.update(manifest['__pkg_dir'], version, only_check)
requirements = self.packages[name].get("version", "")
if "://" in requirements:
_, requirements, __ = self.parse_pkg_uri(requirements)
self.pm.update(manifest['__pkg_dir'], requirements, only_check)
def get_installed_packages(self):
items = {}
@ -310,18 +302,19 @@ class PlatformPackagesMixin(object):
def are_outdated_packages(self):
for name, manifest in self.get_installed_packages().items():
version = self.packages[name].get("version", "")
if "@" in version and not version.startswith("git@"):
_, version = version.rsplit("@", 1)
if self.pm.outdated(manifest['__pkg_dir'], version):
requirements = self.packages[name].get("version", "")
if "://" in requirements:
_, requirements, __ = self.parse_pkg_uri(requirements)
if self.pm.outdated(manifest['__pkg_dir'], requirements):
return True
return False
def get_package_dir(self, name):
version = self.packages[name].get("version", "")
if self.is_valid_requirements(version):
return self.pm.get_package_dir(name, version)
return self.pm.get_package_dir(*self._parse_pkg_input(name, version))
if "://" in version:
return self.pm.get_package_dir(*self.pm.parse_pkg_uri(
"%s=%s" % (name, version)))
return self.pm.get_package_dir(name, version)
def get_package_version(self, name):
pkg_dir = self.get_package_dir(name)
@ -329,16 +322,6 @@ class PlatformPackagesMixin(object):
return None
return self.pm.load_manifest(pkg_dir).get("version")
@staticmethod
def is_valid_requirements(requirements):
return requirements and ":" not in requirements
def _parse_pkg_input(self, name, version):
requirements = None
if "@" in version and not version.startswith("git@"):
version, requirements = version.rsplit("@", 1)
return self.pm.parse_pkg_input("%s=%s" % (name, version), requirements)
class PlatformRunMixin(object):

View File

@ -115,14 +115,14 @@ def test_pkg_input_parser():
"hg+https://example.com/user/package",
("package", None, "hg+https://example.com/user/package")
],
[
"git@github.com:user/package.git",
("package", None, "git@github.com:user/package.git")
],
[
"git@github.com:user/package.git#v1.2.0",
("package", None, "git@github.com:user/package.git#v1.2.0")
],
# [
# "git@github.com:user/package.git",
# ("package", None, "git@github.com:user/package.git")
# ],
# [
# "git@github.com:user/package.git#v1.2.0",
# ("package", None, "git@github.com:user/package.git#v1.2.0")
# ],
[
"git+ssh://git@gitlab.private-server.com/user/package#1.2.0",
("package", None,
@ -132,13 +132,19 @@ def test_pkg_input_parser():
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0",
("package", None,
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0")
],
[
"LocalName=git+ssh://user@gitlab.private-server.com:1234"
"/package#1.2.0@!=13",
("LocalName", "!=13",
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0")
]
]
for params, result in items:
if isinstance(params, tuple):
assert PackageManager.parse_pkg_input(*params) == result
assert PackageManager.parse_pkg_uri(*params) == result
else:
assert PackageManager.parse_pkg_input(params) == result
assert PackageManager.parse_pkg_uri(params) == result
def test_install_packages(isolated_pio_home, tmpdir):