Skip to content

Commit 6f11f81

Browse files
committed
Ignore files according to the patterns declared in ".gitignore" when using pio package pack // Resolve #4188
1 parent 4191a9b commit 6f11f81

File tree

5 files changed

+68
-8
lines changed

5 files changed

+68
-8
lines changed

HISTORY.rst

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ PlatformIO Core 5
1919
* `pio pkg exec <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_exec.html>`_ - run command from package tool (`issue #4163 <https://github.com/platformio/platformio-core/issues/4163>`_)
2020

2121
- Added support for dependencies declared in a "tool" type package
22+
- Ignore files according to the patterns declared in ".gitignore" when using `pio package pack <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_pack.html>`__ command (`issue #4188 <https://github.com/platformio/platformio-core/issues/4188>`_)
2223
- Dropped automatic updates of global libraries and development platforms (`issue #4179 <https://github.com/platformio/platformio-core/issues/4179>`_)
2324
- Dropped support for "pythonPackages" field in "platform.json" manifest in favor of `Extra Python Dependencies <https://docs.platformio.org/en/latest/scripting/examples/extra_python_packages.html>`__
2425

docs

platformio/package/pack.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@
3333

3434

3535
class PackagePacker(object):
36-
INCLUDE_DEFAULT = ManifestFileType.items().values()
36+
INCLUDE_DEFAULT = list(ManifestFileType.items().values()) + [
37+
"README",
38+
"README.md",
39+
"README.rst",
40+
"LICENSE",
41+
]
3742
EXCLUDE_DEFAULT = [
3843
# PlatformIO internal files
3944
PackageItem.METAFILE_NAME,
@@ -125,6 +130,20 @@ def get_archive_name(name, version, system=None):
125130
),
126131
)
127132

133+
@staticmethod
134+
def load_gitignore_filters(path):
135+
result = []
136+
with open(path, encoding="utf8") as fp:
137+
for line in fp.readlines():
138+
line = line.strip()
139+
if not line or line.startswith(("#")):
140+
continue
141+
if line.startswith("!"):
142+
result.append(f"+<{line[1:]}>")
143+
else:
144+
result.append(f"-<{line}>")
145+
return result
146+
128147
def pack(self, dst=None):
129148
tmp_dir = tempfile.mkdtemp()
130149
try:
@@ -156,7 +175,7 @@ def pack(self, dst=None):
156175
elif os.path.isdir(dst):
157176
dst = os.path.join(dst, filename)
158177

159-
return self._create_tarball(src, dst, manifest)
178+
return self.create_tarball(src, dst, manifest)
160179
finally:
161180
shutil.rmtree(tmp_dir)
162181

@@ -183,7 +202,7 @@ def find_source_root(self, src):
183202

184203
return src
185204

186-
def _create_tarball(self, src, dst, manifest):
205+
def create_tarball(self, src, dst, manifest):
187206
include = manifest.get("export", {}).get("include")
188207
exclude = manifest.get("export", {}).get("exclude")
189208
# remap root
@@ -224,11 +243,15 @@ def compute_src_filters(self, src, include, exclude):
224243
result += ["-<%s>" % p for p in self.EXCLUDE_DEFAULT]
225244
# exclude items declared in manifest
226245
result += ["-<%s>" % p for p in exclude or []]
246+
227247
# apply extra excludes if no custom "export" field in manifest
228248
if (not include and not exclude) or isinstance(
229249
self.manifest_parser, LibraryPropertiesManifestParser
230250
):
231251
result += ["-<%s>" % p for p in exclude_extra]
232-
# automatically include manifests
252+
if os.path.exists(os.path.join(src, ".gitignore")):
253+
result += self.load_gitignore_filters(os.path.join(src, ".gitignore"))
254+
255+
# always include manifests and relevant files
233256
result += ["+<%s>" % p for p in self.INCLUDE_DEFAULT]
234257
return result

tests/package/test_pack.py

+38-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
def test_base(tmpdir_factory):
2828
pkg_dir = tmpdir_factory.mktemp("package")
2929
pkg_dir.join(".git").mkdir().join("file").write("")
30-
pkg_dir.join(".gitignore").write("tests")
31-
pkg_dir.join("._ignored").write("")
30+
pkg_dir.join(".gitignore").write("")
31+
pkg_dir.join("._hidden_file").write("")
3232
pkg_dir.join("main.cpp").write("#include <stdio.h>")
3333
p = PackagePacker(str(pkg_dir))
3434
# test missed manifest
@@ -95,6 +95,42 @@ def test_filters(tmpdir_factory):
9595
)
9696

9797

98+
def test_gitgnore_filters(tmpdir_factory):
99+
pkg_dir = tmpdir_factory.mktemp("package")
100+
pkg_dir.join(".git").mkdir().join("file").write("")
101+
pkg_dir.join(".gitignore").write(
102+
"""
103+
# comment
104+
105+
gi_file
106+
gi_folder
107+
gi_folder_*
108+
109+
**/main_nested.h
110+
111+
gi_keep_file
112+
!gi_keep_file
113+
LICENSE
114+
"""
115+
)
116+
pkg_dir.join("LICENSE").write("")
117+
pkg_dir.join("gi_keep_file").write("")
118+
pkg_dir.join("gi_file").write("")
119+
pkg_dir.mkdir("gi_folder").join("main.h").write("#ifndef")
120+
pkg_dir.mkdir("gi_folder_name").join("main.h").write("#ifndef")
121+
pkg_dir.mkdir("gi_nested_folder").mkdir("a").mkdir("b").join("main_nested.h").write(
122+
"#ifndef"
123+
)
124+
pkg_dir.join("library.json").write('{"name": "foo", "version": "1.0.0"}')
125+
p = PackagePacker(str(pkg_dir))
126+
with fs.cd(str(pkg_dir)):
127+
p.pack()
128+
with tarfile.open(os.path.join(str(pkg_dir), "foo-1.0.0.tar.gz"), "r:gz") as tar:
129+
assert set(tar.getnames()) == set(
130+
["library.json", "LICENSE", ".gitignore", "gi_keep_file"]
131+
)
132+
133+
98134
def test_symlinks(tmpdir_factory):
99135
# Windows does not support symbolic links
100136
if IS_WINDOWS:

0 commit comments

Comments
 (0)