mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-29 17:47: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
|
||||
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")
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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):
|
||||
|
Reference in New Issue
Block a user