environment: handle view root at existing directory better (#45263)

- remove empty dir if exists at view root
- error better if non-empty dir

Co-authored-by: Harmen Stoppels <me@harmenstoppels.nl>
This commit is contained in:
Wouter Deconinck 2024-07-17 16:17:30 -05:00 committed by GitHub
parent 4710cbb281
commit b869538544
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 0 deletions

View File

@ -5,6 +5,7 @@
import collections
import collections.abc
import contextlib
import errno
import os
import pathlib
import re
@ -788,6 +789,23 @@ def regenerate(self, concrete_roots: List[Spec]) -> None:
root_dirname = os.path.dirname(self.root)
tmp_symlink_name = os.path.join(root_dirname, "._view_link")
# Remove self.root if is it an empty dir, since we need a symlink there. Note that rmdir
# fails if self.root is a symlink.
try:
os.rmdir(self.root)
except (FileNotFoundError, NotADirectoryError):
pass
except OSError as e:
if e.errno == errno.ENOTEMPTY:
msg = "it is a non-empty directory"
elif e.errno == errno.EACCES:
msg = "of insufficient permissions"
else:
raise
raise SpackEnvironmentViewError(
f"The environment view in {self.root} cannot not be created because {msg}."
) from e
# Create a new view
try:
fs.mkdirp(new_root)

View File

@ -841,3 +841,28 @@ def test_root_version_weights_for_old_versions(mutable_mock_env_path, mock_packa
assert bowtie.satisfies("@=1.3.0")
assert gcc.satisfies("@=1.0")
def test_env_view_on_empty_dir_is_fine(tmp_path, config, mock_packages, temporary_store):
"""Tests that creating a view pointing to an empty dir is not an error."""
view_dir = tmp_path / "view"
view_dir.mkdir()
env = ev.create_in_dir(tmp_path, with_view="view")
env.add("mpileaks")
env.concretize()
env.install_all(fake=True)
env.regenerate_views()
assert view_dir.is_symlink()
def test_env_view_on_non_empty_dir_errors(tmp_path, config, mock_packages, temporary_store):
"""Tests that creating a view pointing to a non-empty dir errors."""
view_dir = tmp_path / "view"
view_dir.mkdir()
(view_dir / "file").write_text("")
env = ev.create_in_dir(tmp_path, with_view="view")
env.add("mpileaks")
env.concretize()
env.install_all(fake=True)
with pytest.raises(ev.SpackEnvironmentError, match="because it is a non-empty dir"):
env.regenerate_views()