Skip to content

Commit 41f2c7c

Browse files
authored
Distribution extra spack cleanup (#640)
* Minor fixes fix tests to be robust to non-breaking api changes. Also, change binary asset check so it is not recursive. This avoids an infinite loop in some environments. * When bundling spack with a distribution don't include user files The distribution command was including files specific to the user's spack environment were getting bundled along with spack. This is becasue spack writes into its root directory as it is being used. This creates a more exhaustive list of locations to avoid copying along with spack and more agressively asserts they don't end up in the final spack installation
1 parent 9f49104 commit 41f2c7c

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

manager/manager_cmds/distribution.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fnmatch
2+
import glob
23
import os
34
import shutil
45

@@ -20,6 +21,9 @@
2021
level = "long"
2122

2223

24+
SPACK_USER_PATTERNS = ["var/*", "opt/*", ".git*", "etc/spack/*"]
25+
26+
2327
def add_command(parser, command_dict):
2428
subparser = parser.add_parser("distribution", help=description)
2529
subparser.add_argument(
@@ -139,8 +143,7 @@ def valid_env_scopes(env):
139143

140144
def bundle_spack(location):
141145
tty.msg(f"Packing up Spack installation to {location}....")
142-
ignore_these = ["var/spack/environments/*", "opt/*", ".git*", "etc/spack/include.yaml"]
143-
copy_files_excluding_pattern(spack_root, location, ignore_these)
146+
copy_files_excluding_pattern(spack_root, location, SPACK_USER_PATTERNS)
144147

145148

146149
class DistributionPackager:
@@ -205,6 +208,8 @@ def concretize(self):
205208
self.env.write()
206209

207210
def remove_unwanted_artifacts(self):
211+
for pattern in SPACK_USER_PATTERNS:
212+
remove_by_pattern(os.path.join(self.spack_dir, pattern))
208213
for item in os.listdir(self.env.path):
209214
fullname = os.path.join(self.env.path, item)
210215
if "spack.yaml" in item:
@@ -413,6 +418,15 @@ def correct_mirror_args(env, args):
413418
args.source_only = True
414419

415420

421+
def remove_by_pattern(pattern):
422+
for item in glob.glob(pattern, recursive=True):
423+
tty.msg(item)
424+
if os.path.isfile(item):
425+
os.remove(item)
426+
elif os.path.isdir(item):
427+
shutil.rmtree(item)
428+
429+
416430
def distribution(parser, args):
417431
env = spack.cmd.require_active_env(cmd_name="manager distribution")
418432
correct_mirror_args(env, args)

tests/test_distribution.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,34 @@ def test_copy_files_excluding_pattern(tmpdir):
126126
assert len(results) == 3
127127

128128

129+
def test_remove_by_pattern(tmpdir):
130+
"""
131+
Test the removal of all files/dirs from a higherarchy that match a passed glob pattern.
132+
"""
133+
root = os.path.join(tmpdir.strpath, "foo")
134+
good = [
135+
os.path.join(root, "bar", "file.txt"),
136+
os.path.join(root, "bar", "bong", "bad.txt"),
137+
os.path.join(root, "baz", "file.txt"),
138+
]
139+
140+
bad_root = os.path.join(root, "bing")
141+
bad = [os.path.join(bad_root, "bang", "bad.txt"), os.path.join(bad_root, "bing", "file.txt")]
142+
143+
for p in good + bad:
144+
os.makedirs(os.path.dirname(p), exist_ok=True)
145+
with open(p, "w") as f:
146+
f.write("content")
147+
148+
distribution.remove_by_pattern(f"{bad_root}/*")
149+
150+
for bad_p in bad:
151+
assert not os.path.isfile(bad_p)
152+
for good_p in good:
153+
assert os.path.isfile(good_p)
154+
assert os.path.isdir(bad_root)
155+
156+
129157
def test_remove_subset_from_dict():
130158
"""
131159
This test verifies that the `remove_subset_from_dict` function correctly removes specified keys
@@ -453,7 +481,7 @@ def test_concretzie(tmpdir):
453481
assert os.path.isfile(lockfile)
454482

455483

456-
def test_DistributionPackager_remove_unwanted_artifacts(tmpdir):
484+
def test_DistributionPackager_remove_unwanted_artifacts(tmpdir, monkeypatch):
457485
"""
458486
This test verifies that `remove_unwanted_artifacts` removes files
459487
created by concretizing the environment.
@@ -466,13 +494,19 @@ def test_DistributionPackager_remove_unwanted_artifacts(tmpdir):
466494

467495
pkgr = distribution.DistributionPackager(None, root)
468496
pkgr._env = env
469-
470497
pkgr.concretize()
471498
assert len(os.listdir(env_dir)) == 3
499+
bad_file = os.path.join(pkgr.spack_dir, "foo", "aFile")
500+
os.makedirs(os.path.dirname(bad_file))
501+
with open(bad_file, "w") as out:
502+
out.write("content")
503+
monkeypatch.setattr(distribution, "SPACK_USER_PATTERNS", ["foo/*"])
504+
472505
pkgr.remove_unwanted_artifacts()
473506
env_assets = os.listdir(env_dir)
474507
assert len(env_assets) == 1
475508
assert "spack.yaml" in env_assets
509+
assert not os.path.isfile(bad_file)
476510

477511

478512
def test_DistributionPackager_configure_includes(tmpdir):

0 commit comments

Comments
 (0)