diff options
-rw-r--r-- | lib/spack/spack/hooks/sbang.py | 12 | ||||
-rw-r--r-- | lib/spack/spack/test/sbang.py | 17 |
2 files changed, 26 insertions, 3 deletions
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py index 3a957c6e0e..02c1ce3816 100644 --- a/lib/spack/spack/hooks/sbang.py +++ b/lib/spack/spack/hooks/sbang.py @@ -23,6 +23,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import os +import stat import re import llnl.util.tty as tty @@ -62,10 +63,21 @@ def filter_shebang(path): if re.search(r'^#!(/[^/]*)*lua\b', original): original = re.sub(r'^#', '--', original) + # Change non-writable files to be writable if needed. + saved_mode = None + if not os.access(path, os.W_OK): + st = os.stat(path) + saved_mode = st.st_mode + os.chmod(path, saved_mode | stat.S_IWRITE) + with open(path, 'w') as new_file: new_file.write(new_sbang_line) new_file.write(original) + # Restore original permissions. + if saved_mode is not None: + os.chmod(path, saved_mode) + tty.warn("Patched overlong shebang in %s" % path) diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py index ed54ff90b0..4ce854a1d8 100644 --- a/lib/spack/spack/test/sbang.py +++ b/lib/spack/spack/test/sbang.py @@ -26,6 +26,7 @@ Test that Spack's shebang filtering works correctly. """ import os +import stat import unittest import tempfile import shutil @@ -41,6 +42,7 @@ lua_line_patched = "--!/this/" + ('x' * 200) + "/is/lua\n" sbang_line = '#!/bin/bash %s/bin/sbang\n' % spack.spack_root last_line = "last!\n" + class SbangTest(unittest.TestCase): def setUp(self): self.tempdir = tempfile.mkdtemp() @@ -74,10 +76,8 @@ class SbangTest(unittest.TestCase): f.write(long_line) f.write(last_line) - def tearDown(self): - shutil.rmtree(self.tempdir, ignore_errors=True) - + shutil.rmtree(self.tempdir, ignore_errors=True) def test_shebang_handling(self): filter_shebangs_in_directory(self.tempdir) @@ -104,3 +104,14 @@ class SbangTest(unittest.TestCase): self.assertEqual(f.readline(), sbang_line) self.assertEqual(f.readline(), long_line) self.assertEqual(f.readline(), last_line) + + def test_shebang_handles_non_writable_files(self): + # make a file non-writable + st = os.stat(self.long_shebang) + not_writable_mode = st.st_mode & ~stat.S_IWRITE + os.chmod(self.long_shebang, not_writable_mode) + + self.test_shebang_handling() + + st = os.stat(self.long_shebang) + self.assertEqual(oct(not_writable_mode), oct(st.st_mode)) |