diff --git a/platformio/package/exception.py b/platformio/package/exception.py index 3927505d..7804e519 100644 --- a/platformio/package/exception.py +++ b/platformio/package/exception.py @@ -15,7 +15,11 @@ from platformio.exception import PlatformioException -class ManifestException(PlatformioException): +class PackageException(PlatformioException): + pass + + +class ManifestException(PackageException): pass diff --git a/platformio/package/pack.py b/platformio/package/pack.py index c58b84a3..5ed5749a 100644 --- a/platformio/package/pack.py +++ b/platformio/package/pack.py @@ -18,6 +18,7 @@ import tarfile import tempfile from platformio import fs +from platformio.package.exception import PackageException from platformio.package.manifest.parser import ManifestFileType, ManifestParserFactory from platformio.package.manifest.schema import ManifestSchema from platformio.unpacker import FileUnpacker @@ -27,8 +28,9 @@ class PackagePacker(object): EXCLUDE_DEFAULT = ["._*", ".DS_Store", ".git", ".hg", ".svn", ".pio"] INCLUDE_DEFAULT = ManifestFileType.items().values() - def __init__(self, package): + def __init__(self, package, manifest_uri=None): self.package = package + self.manifest_uri = manifest_uri def pack(self, dst=None): tmp_dir = tempfile.mkdtemp() @@ -41,6 +43,8 @@ class PackagePacker(object): assert fu.unpack(tmp_dir, silent=True) src = tmp_dir + src = self.find_source_root(src) + manifest = self.load_manifest(src) filename = "{name}{system}-{version}.tar.gz".format( name=manifest["name"], @@ -67,6 +71,29 @@ class PackagePacker(object): mp = ManifestParserFactory.new_from_dir(src) 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): # remap root if ( diff --git a/tests/package/test_pack.py b/tests/package/test_pack.py index 91565213..a0af0172 100644 --- a/tests/package/test_pack.py +++ b/tests/package/test_pack.py @@ -56,9 +56,7 @@ def test_filters(tmpdir_factory): json.dumps(dict(name="bar", version="1.2.3", export={"include": "src"})) ) p = PackagePacker(str(pkg_dir)) - dst = os.path.join(str(pkg_dir), "tarball.tar.gz") - p.pack(dst) - with tarfile.open(dst, "r:gz") as tar: + with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: assert set(tar.getnames()) == set(["util/helpers.cpp", "main.cpp"]) # test include "src" and "include" @@ -68,9 +66,7 @@ def test_filters(tmpdir_factory): ) ) p = PackagePacker(str(pkg_dir)) - dst = os.path.join(str(pkg_dir), "tarball.tar.gz") - p.pack(dst) - with tarfile.open(dst, "r:gz") as tar: + with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: assert set(tar.getnames()) == set( ["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)) - dst = os.path.join(str(pkg_dir), "tarball.tar.gz") - p.pack(dst) - with tarfile.open(dst, "r:gz") as tar: + with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: assert set(tar.getnames()) == set( ["library.json", "src/main.cpp", "src/util/helpers.cpp"] ) @@ -114,3 +108,35 @@ def test_symlinks(tmpdir_factory): ) m = tar.getmember("src/main.h") 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 ") + 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 ") + 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"]) diff --git a/tests/test_examples.py b/tests/test_examples.py index eac51469..b0d0dfcb 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -20,6 +20,7 @@ from os.path import basename, dirname, getsize, isdir, isfile, join, normpath import pytest from platformio import util +from platformio.compat import PY2 from platformio.managers.platform import PlatformFactory, PlatformManager from platformio.project.config import ProjectConfig @@ -53,6 +54,8 @@ def pytest_generate_tests(metafunc): for root, _, files in walk(examples_dir): if "platformio.ini" not in files or ".skiptest" in files: continue + if "zephyr-" in root and PY2: + continue group = basename(root) if "-" in group: group = group.split("-", 1)[0]