From 6f11f812f8d14972a8cf4f830244f8bf091784e6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 23 Feb 2022 18:46:53 +0200 Subject: [PATCH] Ignore files according to the patterns declared in ".gitignore" when using `pio package pack` // Resolve #4188 --- HISTORY.rst | 1 + docs | 2 +- examples | 2 +- platformio/package/pack.py | 31 +++++++++++++++++++++++++---- tests/package/test_pack.py | 40 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 14fb0147..e886594a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,6 +19,7 @@ PlatformIO Core 5 * `pio pkg exec `_ - run command from package tool (`issue #4163 `_) - Added support for dependencies declared in a "tool" type package + - Ignore files according to the patterns declared in ".gitignore" when using `pio package pack `__ command (`issue #4188 `_) - Dropped automatic updates of global libraries and development platforms (`issue #4179 `_) - Dropped support for "pythonPackages" field in "platform.json" manifest in favor of `Extra Python Dependencies `__ diff --git a/docs b/docs index 02ab9fd4..0e834b92 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 02ab9fd4d204dd0f9d4332b0ce1209417d9e4441 +Subproject commit 0e834b92f74f88ba7974bc1caa0d652b4b9a055b diff --git a/examples b/examples index dcafbd19..35d7abd4 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit dcafbd192ee19fdb310136fa62335a3ce13ec517 +Subproject commit 35d7abd4591e96bdf3fc316fef245652b775d22c diff --git a/platformio/package/pack.py b/platformio/package/pack.py index 84d835ed..b345c053 100644 --- a/platformio/package/pack.py +++ b/platformio/package/pack.py @@ -33,7 +33,12 @@ from platformio.package.unpack import FileUnpacker class PackagePacker(object): - INCLUDE_DEFAULT = ManifestFileType.items().values() + INCLUDE_DEFAULT = list(ManifestFileType.items().values()) + [ + "README", + "README.md", + "README.rst", + "LICENSE", + ] EXCLUDE_DEFAULT = [ # PlatformIO internal files PackageItem.METAFILE_NAME, @@ -125,6 +130,20 @@ class PackagePacker(object): ), ) + @staticmethod + def load_gitignore_filters(path): + result = [] + with open(path, encoding="utf8") as fp: + for line in fp.readlines(): + line = line.strip() + if not line or line.startswith(("#")): + continue + if line.startswith("!"): + result.append(f"+<{line[1:]}>") + else: + result.append(f"-<{line}>") + return result + def pack(self, dst=None): tmp_dir = tempfile.mkdtemp() try: @@ -156,7 +175,7 @@ class PackagePacker(object): elif os.path.isdir(dst): dst = os.path.join(dst, filename) - return self._create_tarball(src, dst, manifest) + return self.create_tarball(src, dst, manifest) finally: shutil.rmtree(tmp_dir) @@ -183,7 +202,7 @@ class PackagePacker(object): return src - def _create_tarball(self, src, dst, manifest): + def create_tarball(self, src, dst, manifest): include = manifest.get("export", {}).get("include") exclude = manifest.get("export", {}).get("exclude") # remap root @@ -224,11 +243,15 @@ class PackagePacker(object): result += ["-<%s>" % p for p in self.EXCLUDE_DEFAULT] # exclude items declared in manifest result += ["-<%s>" % p for p in exclude or []] + # apply extra excludes if no custom "export" field in manifest if (not include and not exclude) or isinstance( self.manifest_parser, LibraryPropertiesManifestParser ): result += ["-<%s>" % p for p in exclude_extra] - # automatically include manifests + if os.path.exists(os.path.join(src, ".gitignore")): + result += self.load_gitignore_filters(os.path.join(src, ".gitignore")) + + # always include manifests and relevant files result += ["+<%s>" % p for p in self.INCLUDE_DEFAULT] return result diff --git a/tests/package/test_pack.py b/tests/package/test_pack.py index cc898f9d..558591b3 100644 --- a/tests/package/test_pack.py +++ b/tests/package/test_pack.py @@ -27,8 +27,8 @@ from platformio.package.pack import PackagePacker def test_base(tmpdir_factory): pkg_dir = tmpdir_factory.mktemp("package") pkg_dir.join(".git").mkdir().join("file").write("") - pkg_dir.join(".gitignore").write("tests") - pkg_dir.join("._ignored").write("") + pkg_dir.join(".gitignore").write("") + pkg_dir.join("._hidden_file").write("") pkg_dir.join("main.cpp").write("#include ") p = PackagePacker(str(pkg_dir)) # test missed manifest @@ -95,6 +95,42 @@ def test_filters(tmpdir_factory): ) +def test_gitgnore_filters(tmpdir_factory): + pkg_dir = tmpdir_factory.mktemp("package") + pkg_dir.join(".git").mkdir().join("file").write("") + pkg_dir.join(".gitignore").write( + """ +# comment + +gi_file +gi_folder +gi_folder_* + +**/main_nested.h + +gi_keep_file +!gi_keep_file +LICENSE +""" + ) + pkg_dir.join("LICENSE").write("") + pkg_dir.join("gi_keep_file").write("") + pkg_dir.join("gi_file").write("") + pkg_dir.mkdir("gi_folder").join("main.h").write("#ifndef") + pkg_dir.mkdir("gi_folder_name").join("main.h").write("#ifndef") + pkg_dir.mkdir("gi_nested_folder").mkdir("a").mkdir("b").join("main_nested.h").write( + "#ifndef" + ) + pkg_dir.join("library.json").write('{"name": "foo", "version": "1.0.0"}') + p = PackagePacker(str(pkg_dir)) + with fs.cd(str(pkg_dir)): + p.pack() + with tarfile.open(os.path.join(str(pkg_dir), "foo-1.0.0.tar.gz"), "r:gz") as tar: + assert set(tar.getnames()) == set( + ["library.json", "LICENSE", ".gitignore", "gi_keep_file"] + ) + + def test_symlinks(tmpdir_factory): # Windows does not support symbolic links if IS_WINDOWS: