sbang filtering now works on non-writable files. (#1445)

- sbang now changes mode to writable and restores mode if a file is not
  writable.
This commit is contained in:
Todd Gamblin 2016-08-04 10:46:45 -07:00 committed by GitHub
parent 369b2ef01f
commit 6ab78eb88e
2 changed files with 26 additions and 3 deletions

View File

@ -23,6 +23,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os import os
import stat
import re import re
import llnl.util.tty as tty import llnl.util.tty as tty
@ -62,10 +63,21 @@ def filter_shebang(path):
if re.search(r'^#!(/[^/]*)*lua\b', original): if re.search(r'^#!(/[^/]*)*lua\b', original):
original = re.sub(r'^#', '--', 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: with open(path, 'w') as new_file:
new_file.write(new_sbang_line) new_file.write(new_sbang_line)
new_file.write(original) 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) tty.warn("Patched overlong shebang in %s" % path)

View File

@ -26,6 +26,7 @@
Test that Spack's shebang filtering works correctly. Test that Spack's shebang filtering works correctly.
""" """
import os import os
import stat
import unittest import unittest
import tempfile import tempfile
import shutil import shutil
@ -41,6 +42,7 @@
sbang_line = '#!/bin/bash %s/bin/sbang\n' % spack.spack_root sbang_line = '#!/bin/bash %s/bin/sbang\n' % spack.spack_root
last_line = "last!\n" last_line = "last!\n"
class SbangTest(unittest.TestCase): class SbangTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.tempdir = tempfile.mkdtemp() self.tempdir = tempfile.mkdtemp()
@ -74,10 +76,8 @@ def setUp(self):
f.write(long_line) f.write(long_line)
f.write(last_line) f.write(last_line)
def tearDown(self): def tearDown(self):
shutil.rmtree(self.tempdir, ignore_errors=True) shutil.rmtree(self.tempdir, ignore_errors=True)
def test_shebang_handling(self): def test_shebang_handling(self):
filter_shebangs_in_directory(self.tempdir) filter_shebangs_in_directory(self.tempdir)
@ -104,3 +104,14 @@ def test_shebang_handling(self):
self.assertEqual(f.readline(), sbang_line) self.assertEqual(f.readline(), sbang_line)
self.assertEqual(f.readline(), long_line) self.assertEqual(f.readline(), long_line)
self.assertEqual(f.readline(), last_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))