Support packages with nested folders and with a custom "root"

This commit is contained in:
Ivan Kravets
2020-01-03 22:55:56 +02:00
parent 8d7b775875
commit ec82fc82a2
4 changed files with 71 additions and 11 deletions

View File

@ -15,7 +15,11 @@
from platformio.exception import PlatformioException from platformio.exception import PlatformioException
class ManifestException(PlatformioException): class PackageException(PlatformioException):
pass
class ManifestException(PackageException):
pass pass

View File

@ -18,6 +18,7 @@ import tarfile
import tempfile import tempfile
from platformio import fs from platformio import fs
from platformio.package.exception import PackageException
from platformio.package.manifest.parser import ManifestFileType, ManifestParserFactory from platformio.package.manifest.parser import ManifestFileType, ManifestParserFactory
from platformio.package.manifest.schema import ManifestSchema from platformio.package.manifest.schema import ManifestSchema
from platformio.unpacker import FileUnpacker from platformio.unpacker import FileUnpacker
@ -27,8 +28,9 @@ class PackagePacker(object):
EXCLUDE_DEFAULT = ["._*", ".DS_Store", ".git", ".hg", ".svn", ".pio"] EXCLUDE_DEFAULT = ["._*", ".DS_Store", ".git", ".hg", ".svn", ".pio"]
INCLUDE_DEFAULT = ManifestFileType.items().values() INCLUDE_DEFAULT = ManifestFileType.items().values()
def __init__(self, package): def __init__(self, package, manifest_uri=None):
self.package = package self.package = package
self.manifest_uri = manifest_uri
def pack(self, dst=None): def pack(self, dst=None):
tmp_dir = tempfile.mkdtemp() tmp_dir = tempfile.mkdtemp()
@ -41,6 +43,8 @@ class PackagePacker(object):
assert fu.unpack(tmp_dir, silent=True) assert fu.unpack(tmp_dir, silent=True)
src = tmp_dir src = tmp_dir
src = self.find_source_root(src)
manifest = self.load_manifest(src) manifest = self.load_manifest(src)
filename = "{name}{system}-{version}.tar.gz".format( filename = "{name}{system}-{version}.tar.gz".format(
name=manifest["name"], name=manifest["name"],
@ -67,6 +71,29 @@ class PackagePacker(object):
mp = ManifestParserFactory.new_from_dir(src) mp = ManifestParserFactory.new_from_dir(src)
return ManifestSchema().load_manifest(mp.as_dict()) return ManifestSchema().load_manifest(mp.as_dict())
def find_source_root(self, src):
if self.manifest_uri:
mp = (
ManifestParserFactory.new_from_file(self.manifest_uri[5:])
if self.manifest_uri.startswith("file:")
else ManifestParserFactory.new_from_url(self.manifest_uri)
)
manifest = ManifestSchema().load_manifest(mp.as_dict())
include = manifest.get("export", {}).get("include", [])
if len(include) == 1:
if not os.path.isdir(os.path.join(src, include[0])):
raise PackageException(
"Non existing `include` directory `%s` in a package"
% include[0]
)
return os.path.join(src, include[0])
for root, _, __ in os.walk(src):
if ManifestFileType.from_dir(root):
return root
return src
def _create_tarball(self, src, dst, include=None, exclude=None): def _create_tarball(self, src, dst, include=None, exclude=None):
# remap root # remap root
if ( if (

View File

@ -56,9 +56,7 @@ def test_filters(tmpdir_factory):
json.dumps(dict(name="bar", version="1.2.3", export={"include": "src"})) json.dumps(dict(name="bar", version="1.2.3", export={"include": "src"}))
) )
p = PackagePacker(str(pkg_dir)) p = PackagePacker(str(pkg_dir))
dst = os.path.join(str(pkg_dir), "tarball.tar.gz") with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar:
p.pack(dst)
with tarfile.open(dst, "r:gz") as tar:
assert set(tar.getnames()) == set(["util/helpers.cpp", "main.cpp"]) assert set(tar.getnames()) == set(["util/helpers.cpp", "main.cpp"])
# test include "src" and "include" # test include "src" and "include"
@ -68,9 +66,7 @@ def test_filters(tmpdir_factory):
) )
) )
p = PackagePacker(str(pkg_dir)) p = PackagePacker(str(pkg_dir))
dst = os.path.join(str(pkg_dir), "tarball.tar.gz") with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar:
p.pack(dst)
with tarfile.open(dst, "r:gz") as tar:
assert set(tar.getnames()) == set( assert set(tar.getnames()) == set(
["include/main.h", "library.json", "src/main.cpp", "src/util/helpers.cpp"] ["include/main.h", "library.json", "src/main.cpp", "src/util/helpers.cpp"]
) )
@ -86,9 +82,7 @@ def test_filters(tmpdir_factory):
) )
) )
p = PackagePacker(str(pkg_dir)) p = PackagePacker(str(pkg_dir))
dst = os.path.join(str(pkg_dir), "tarball.tar.gz") with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar:
p.pack(dst)
with tarfile.open(dst, "r:gz") as tar:
assert set(tar.getnames()) == set( assert set(tar.getnames()) == set(
["library.json", "src/main.cpp", "src/util/helpers.cpp"] ["library.json", "src/main.cpp", "src/util/helpers.cpp"]
) )
@ -114,3 +108,35 @@ def test_symlinks(tmpdir_factory):
) )
m = tar.getmember("src/main.h") m = tar.getmember("src/main.h")
assert m.issym() assert m.issym()
def test_source_root(tmpdir_factory):
pkg_dir = tmpdir_factory.mktemp("package")
root_dir = pkg_dir.mkdir("root")
src_dir = root_dir.mkdir("src")
src_dir.join("main.cpp").write("#include <stdio.h>")
root_dir.join("library.json").write('{"name": "bar", "version": "2.0.0"}')
p = PackagePacker(str(pkg_dir))
with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar:
assert set(tar.getnames()) == set(["library.json", "src/main.cpp"])
def test_manifest_uri(tmpdir_factory):
pkg_dir = tmpdir_factory.mktemp("package")
root_dir = pkg_dir.mkdir("root")
src_dir = root_dir.mkdir("src")
src_dir.join("main.cpp").write("#include <stdio.h>")
root_dir.join("library.json").write('{"name": "foo", "version": "1.0.0"}')
bar_dir = root_dir.mkdir("library").mkdir("bar")
bar_dir.join("library.json").write('{"name": "bar", "version": "2.0.0"}')
bar_dir.mkdir("include").join("bar.h").write("")
manifest_path = pkg_dir.join("remote_library.json")
manifest_path.write(
'{"name": "bar", "version": "3.0.0", "export": {"include": "root/library/bar"}}'
)
p = PackagePacker(str(pkg_dir), manifest_uri="file:%s" % manifest_path)
p.pack(str(pkg_dir))
with tarfile.open(os.path.join(str(pkg_dir), "bar-2.0.0.tar.gz"), "r:gz") as tar:
assert set(tar.getnames()) == set(["library.json", "include/bar.h"])

View File

@ -20,6 +20,7 @@ from os.path import basename, dirname, getsize, isdir, isfile, join, normpath
import pytest import pytest
from platformio import util from platformio import util
from platformio.compat import PY2
from platformio.managers.platform import PlatformFactory, PlatformManager from platformio.managers.platform import PlatformFactory, PlatformManager
from platformio.project.config import ProjectConfig from platformio.project.config import ProjectConfig
@ -53,6 +54,8 @@ def pytest_generate_tests(metafunc):
for root, _, files in walk(examples_dir): for root, _, files in walk(examples_dir):
if "platformio.ini" not in files or ".skiptest" in files: if "platformio.ini" not in files or ".skiptest" in files:
continue continue
if "zephyr-" in root and PY2:
continue
group = basename(root) group = basename(root)
if "-" in group: if "-" in group:
group = group.split("-", 1)[0] group = group.split("-", 1)[0]