mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 10:07:14 +02:00
Improve support for VCS packages
This commit is contained in:
2
docs
2
docs
Submodule docs updated: ea486d6022...0efb6ee60c
@ -128,7 +128,7 @@ def lib_update(lm, libraries, only_check, json_output):
|
|||||||
requirements = None
|
requirements = None
|
||||||
url = None
|
url = None
|
||||||
if not pkg_dir:
|
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)
|
pkg_dir = lm.get_package_dir(name, requirements, url)
|
||||||
if not pkg_dir:
|
if not pkg_dir:
|
||||||
continue
|
continue
|
||||||
@ -314,7 +314,7 @@ def lib_builtin(storage, json_output):
|
|||||||
@click.option("--json-output", is_flag=True)
|
@click.option("--json-output", is_flag=True)
|
||||||
def lib_show(library, json_output):
|
def lib_show(library, json_output):
|
||||||
lm = LibraryManager()
|
lm = LibraryManager()
|
||||||
name, requirements, _ = lm.parse_pkg_input(library)
|
name, requirements, _ = lm.parse_pkg_uri(library)
|
||||||
lib_id = lm.get_pkg_id_by_name(
|
lib_id = lm.get_pkg_id_by_name(
|
||||||
name, requirements, silent=json_output, interactive=not json_output)
|
name, requirements, silent=json_output, interactive=not json_output)
|
||||||
lib = get_api_result("/lib/info/%d" % lib_id, cache_valid="1d")
|
lib = get_api_result("/lib/info/%d" % lib_id, cache_valid="1d")
|
||||||
|
@ -351,7 +351,7 @@ def platform_update(platforms, only_packages, only_check, json_output):
|
|||||||
requirements = None
|
requirements = None
|
||||||
url = None
|
url = None
|
||||||
if not pkg_dir:
|
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)
|
pkg_dir = pm.get_package_dir(name, requirements, url)
|
||||||
if not pkg_dir:
|
if not pkg_dir:
|
||||||
continue
|
continue
|
||||||
|
@ -242,8 +242,7 @@ class LibraryManager(BasePkgManager):
|
|||||||
interactive=False):
|
interactive=False):
|
||||||
pkg_dir = None
|
pkg_dir = None
|
||||||
try:
|
try:
|
||||||
_name, _requirements, _url = self.parse_pkg_input(
|
_name, _requirements, _url = self.parse_pkg_uri(name, requirements)
|
||||||
name, requirements)
|
|
||||||
if not _url:
|
if not _url:
|
||||||
name = "id=%d" % self.get_pkg_id_by_name(
|
name = "id=%d" % self.get_pkg_id_by_name(
|
||||||
_name,
|
_name,
|
||||||
|
@ -490,51 +490,59 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
|
|||||||
click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl)
|
click.echo("%s: %s" % (self.__class__.__name__, message), nl=nl)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_pkg_input( # pylint: disable=too-many-branches
|
def parse_pkg_uri( # pylint: disable=too-many-branches
|
||||||
text, requirements=None):
|
text, requirements=None):
|
||||||
text = str(text)
|
text = str(text)
|
||||||
# git@github.com:user/package.git
|
name, url = None, None
|
||||||
url_marker = text[:4]
|
|
||||||
if url_marker not in ("git@", "git+") or ":" not in text:
|
|
||||||
url_marker = "://"
|
|
||||||
|
|
||||||
|
# Parse requirements
|
||||||
req_conditions = [
|
req_conditions = [
|
||||||
"@" in text,
|
"@" in text, not requirements, "://" not in text
|
||||||
not requirements,
|
or text.rfind("/") < text.rfind("@")
|
||||||
not url_marker.startswith("git")
|
]
|
||||||
] # yapf: disable
|
|
||||||
if all(req_conditions):
|
if all(req_conditions):
|
||||||
text, requirements = text.rsplit("@", 1)
|
text, requirements = text.rsplit("@", 1)
|
||||||
|
|
||||||
|
# Handle PIO Library Registry ID
|
||||||
if text.isdigit():
|
if text.isdigit():
|
||||||
text = "id=" + text
|
text = "id=" + text
|
||||||
|
# Parse custom name
|
||||||
|
elif "=" in text and not text.startswith("id="):
|
||||||
|
name, text = text.split("=", 1)
|
||||||
|
|
||||||
name, url = (None, text)
|
# Parse URL
|
||||||
if "=" in text and not text.startswith("id="):
|
# if valid URL with scheme vcs+protocol://
|
||||||
name, url = text.split("=", 1)
|
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 short version of GitHub URL
|
||||||
# Handle GitHub URL (https://github.com/user/package)
|
if text.count("/") == 1:
|
||||||
url.startswith("https://github.com/") and not url.endswith(
|
url = "git+https://github.com/" + text
|
||||||
(".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 Developer Mbed URL
|
# Parse name from URL
|
||||||
# (https://developer.mbed.org/users/user/code/package/)
|
if url and not name:
|
||||||
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:
|
|
||||||
_url = url.split("#", 1)[0] if "#" in url else url
|
_url = url.split("#", 1)[0] if "#" in url else url
|
||||||
if _url.endswith(("\\", "/")):
|
if _url.endswith(("\\", "/")):
|
||||||
_url = _url[:-1]
|
_url = _url[:-1]
|
||||||
@ -542,8 +550,6 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
|
|||||||
if "." in name and not name.startswith("."):
|
if "." in name and not name.startswith("."):
|
||||||
name = name.rsplit(".", 1)[0]
|
name = name.rsplit(".", 1)[0]
|
||||||
|
|
||||||
if url_marker not in url:
|
|
||||||
url = None
|
|
||||||
return (name or text, requirements, url)
|
return (name or text, requirements, url)
|
||||||
|
|
||||||
def outdated(self, pkg_dir, requirements=None):
|
def outdated(self, pkg_dir, requirements=None):
|
||||||
@ -607,7 +613,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
|
|||||||
return
|
return
|
||||||
self.INSTALL_HISTORY.append(history_key)
|
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)
|
package_dir = self.get_package_dir(name, requirements, url)
|
||||||
|
|
||||||
if not package_dir or not silent:
|
if not package_dir or not silent:
|
||||||
@ -653,8 +659,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
|
|||||||
if isdir(package):
|
if isdir(package):
|
||||||
pkg_dir = package
|
pkg_dir = package
|
||||||
else:
|
else:
|
||||||
name, requirements, url = self.parse_pkg_input(
|
name, requirements, url = self.parse_pkg_uri(package, requirements)
|
||||||
package, requirements)
|
|
||||||
pkg_dir = self.get_package_dir(name, requirements, url)
|
pkg_dir = self.get_package_dir(name, requirements, url)
|
||||||
|
|
||||||
if not pkg_dir:
|
if not pkg_dir:
|
||||||
@ -694,7 +699,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin):
|
|||||||
if isdir(package):
|
if isdir(package):
|
||||||
pkg_dir = package
|
pkg_dir = package
|
||||||
else:
|
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:
|
if not pkg_dir:
|
||||||
raise exception.UnknownPackage("%s @ %s" % (package,
|
raise exception.UnknownPackage("%s @ %s" % (package,
|
||||||
|
@ -84,8 +84,7 @@ class PlatformManager(BasePkgManager):
|
|||||||
if isdir(package):
|
if isdir(package):
|
||||||
pkg_dir = package
|
pkg_dir = package
|
||||||
else:
|
else:
|
||||||
name, requirements, url = self.parse_pkg_input(
|
name, requirements, url = self.parse_pkg_uri(package, requirements)
|
||||||
package, requirements)
|
|
||||||
pkg_dir = self.get_package_dir(name, requirements, url)
|
pkg_dir = self.get_package_dir(name, requirements, url)
|
||||||
|
|
||||||
p = PlatformFactory.newPlatform(pkg_dir)
|
p = PlatformFactory.newPlatform(pkg_dir)
|
||||||
@ -108,8 +107,7 @@ class PlatformManager(BasePkgManager):
|
|||||||
if isdir(package):
|
if isdir(package):
|
||||||
pkg_dir = package
|
pkg_dir = package
|
||||||
else:
|
else:
|
||||||
name, requirements, url = self.parse_pkg_input(
|
name, requirements, url = self.parse_pkg_uri(package, requirements)
|
||||||
package, requirements)
|
|
||||||
pkg_dir = self.get_package_dir(name, requirements, url)
|
pkg_dir = self.get_package_dir(name, requirements, url)
|
||||||
|
|
||||||
p = PlatformFactory.newPlatform(pkg_dir)
|
p = PlatformFactory.newPlatform(pkg_dir)
|
||||||
@ -219,7 +217,7 @@ class PlatformFactory(object):
|
|||||||
platform_dir = dirname(name)
|
platform_dir = dirname(name)
|
||||||
name = util.load_json(name)['name']
|
name = util.load_json(name)['name']
|
||||||
else:
|
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)
|
platform_dir = pm.get_package_dir(name, requirements, url)
|
||||||
if platform_dir:
|
if platform_dir:
|
||||||
name = pm.load_manifest(platform_dir)['name']
|
name = pm.load_manifest(platform_dir)['name']
|
||||||
@ -263,16 +261,10 @@ class PlatformPackagesMixin(object):
|
|||||||
continue
|
continue
|
||||||
elif (name in with_packages or
|
elif (name in with_packages or
|
||||||
not (skip_default_package or opts.get("optional", False))):
|
not (skip_default_package or opts.get("optional", False))):
|
||||||
if self.is_valid_requirements(version):
|
if "://" in version:
|
||||||
self.pm.install(name, version, silent=silent)
|
self.pm.install("%s=%s" % (name, version), silent=silent)
|
||||||
elif version.startswith("git@"):
|
|
||||||
self.pm.install(version, silent=silent)
|
|
||||||
else:
|
else:
|
||||||
requirements = None
|
self.pm.install(name, version, silent=silent)
|
||||||
if "@" in version:
|
|
||||||
version, requirements = version.rsplit("@", 1)
|
|
||||||
self.pm.install(
|
|
||||||
"%s=%s" % (name, version), requirements, silent=silent)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -295,10 +287,10 @@ class PlatformPackagesMixin(object):
|
|||||||
|
|
||||||
def update_packages(self, only_check=False):
|
def update_packages(self, only_check=False):
|
||||||
for name, manifest in self.get_installed_packages().items():
|
for name, manifest in self.get_installed_packages().items():
|
||||||
version = self.packages[name].get("version", "")
|
requirements = self.packages[name].get("version", "")
|
||||||
if "@" in version and not version.startswith("git@"):
|
if "://" in requirements:
|
||||||
_, version = version.rsplit("@", 1)
|
_, requirements, __ = self.parse_pkg_uri(requirements)
|
||||||
self.pm.update(manifest['__pkg_dir'], version, only_check)
|
self.pm.update(manifest['__pkg_dir'], requirements, only_check)
|
||||||
|
|
||||||
def get_installed_packages(self):
|
def get_installed_packages(self):
|
||||||
items = {}
|
items = {}
|
||||||
@ -310,18 +302,19 @@ class PlatformPackagesMixin(object):
|
|||||||
|
|
||||||
def are_outdated_packages(self):
|
def are_outdated_packages(self):
|
||||||
for name, manifest in self.get_installed_packages().items():
|
for name, manifest in self.get_installed_packages().items():
|
||||||
version = self.packages[name].get("version", "")
|
requirements = self.packages[name].get("version", "")
|
||||||
if "@" in version and not version.startswith("git@"):
|
if "://" in requirements:
|
||||||
_, version = version.rsplit("@", 1)
|
_, requirements, __ = self.parse_pkg_uri(requirements)
|
||||||
if self.pm.outdated(manifest['__pkg_dir'], version):
|
if self.pm.outdated(manifest['__pkg_dir'], requirements):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_package_dir(self, name):
|
def get_package_dir(self, name):
|
||||||
version = self.packages[name].get("version", "")
|
version = self.packages[name].get("version", "")
|
||||||
if self.is_valid_requirements(version):
|
if "://" in version:
|
||||||
return self.pm.get_package_dir(name, version)
|
return self.pm.get_package_dir(*self.pm.parse_pkg_uri(
|
||||||
return self.pm.get_package_dir(*self._parse_pkg_input(name, version))
|
"%s=%s" % (name, version)))
|
||||||
|
return self.pm.get_package_dir(name, version)
|
||||||
|
|
||||||
def get_package_version(self, name):
|
def get_package_version(self, name):
|
||||||
pkg_dir = self.get_package_dir(name)
|
pkg_dir = self.get_package_dir(name)
|
||||||
@ -329,16 +322,6 @@ class PlatformPackagesMixin(object):
|
|||||||
return None
|
return None
|
||||||
return self.pm.load_manifest(pkg_dir).get("version")
|
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):
|
class PlatformRunMixin(object):
|
||||||
|
|
||||||
|
@ -115,14 +115,14 @@ def test_pkg_input_parser():
|
|||||||
"hg+https://example.com/user/package",
|
"hg+https://example.com/user/package",
|
||||||
("package", None, "hg+https://example.com/user/package")
|
("package", None, "hg+https://example.com/user/package")
|
||||||
],
|
],
|
||||||
[
|
# [
|
||||||
"git@github.com:user/package.git",
|
# "git@github.com:user/package.git",
|
||||||
("package", None, "git@github.com:user/package.git")
|
# ("package", None, "git@github.com:user/package.git")
|
||||||
],
|
# ],
|
||||||
[
|
# [
|
||||||
"git@github.com:user/package.git#v1.2.0",
|
# "git@github.com:user/package.git#v1.2.0",
|
||||||
("package", None, "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",
|
"git+ssh://git@gitlab.private-server.com/user/package#1.2.0",
|
||||||
("package", None,
|
("package", None,
|
||||||
@ -132,13 +132,19 @@ def test_pkg_input_parser():
|
|||||||
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0",
|
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0",
|
||||||
("package", None,
|
("package", None,
|
||||||
"git+ssh://user@gitlab.private-server.com:1234/package#1.2.0")
|
"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:
|
for params, result in items:
|
||||||
if isinstance(params, tuple):
|
if isinstance(params, tuple):
|
||||||
assert PackageManager.parse_pkg_input(*params) == result
|
assert PackageManager.parse_pkg_uri(*params) == result
|
||||||
else:
|
else:
|
||||||
assert PackageManager.parse_pkg_input(params) == result
|
assert PackageManager.parse_pkg_uri(params) == result
|
||||||
|
|
||||||
|
|
||||||
def test_install_packages(isolated_pio_home, tmpdir):
|
def test_install_packages(isolated_pio_home, tmpdir):
|
||||||
|
Reference in New Issue
Block a user