summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/hooks/sbang.py4
-rw-r--r--lib/spack/spack/test/sbang.py11
2 files changed, 15 insertions, 0 deletions
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
index 1c18c46dc6..ce2cf3435d 100644
--- a/lib/spack/spack/hooks/sbang.py
+++ b/lib/spack/spack/hooks/sbang.py
@@ -110,6 +110,10 @@ def filter_shebang(path):
# Store the file permissions, the patched version needs the same.
saved_mode = os.stat(path).st_mode
+ # Change non-writable files to be writable if needed.
+ if not os.access(path, os.W_OK):
+ os.chmod(path, saved_mode | stat.S_IWUSR)
+
# No need to delete since we'll move it and overwrite the original.
patched = tempfile.NamedTemporaryFile('wb', delete=False)
patched.write(new_sbang_line)
diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py
index e9beebc43d..6d26bd1ba8 100644
--- a/lib/spack/spack/test/sbang.py
+++ b/lib/spack/spack/test/sbang.py
@@ -374,3 +374,14 @@ def test_shebang_exceeds_spack_shebang_limit(shebang_limits_system_8_spack_16, t
with open(file, 'rb') as f:
assert b'sbang' not in f.read()
+
+
+def test_sbang_hook_handles_non_writable_files_preserving_permissions(tmpdir):
+ path = str(tmpdir.join('file.sh'))
+ with open(path, 'w') as f:
+ f.write(long_line)
+ os.chmod(path, 0o555)
+ sbang.filter_shebang(path)
+ with open(path, 'r') as f:
+ assert 'sbang' in f.readline()
+ assert os.stat(path).st_mode & 0o777 == 0o555