Repository: spack/spack

Issue:
lua : sbang prevents luarocks from working
Reproducible by cloning spack in a long enough path and then : 

```
$ spack install lua-luaposix
...
==> Staging archive: /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/lua-5.3.2.tar.gz
==> Created stage in /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd
==> Staging archive: /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/resource-luarocks-urabougj2fmubxqmrsjrzrxk5fn6lhxd/luarocks-2.3.0.tar.gz
==> Created stage in /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/resource-luarocks-urabougj2fmubxqmrsjrzrxk5fn6lhxd
==> Moving resource stage
    source : /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/resource-luarocks-urabougj2fmubxqmrsjrzrxk5fn6lhxd/luarocks-2.3.0/
    destination : /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/lua-5.3.2/luarocks/luarocks
==> No patches needed for lua
==> Building lua
==> Warning: Patched overly long shebang in /home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks-admin
==> Warning: Patched overly long shebang in /home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks-5.3
==> Warning: Patched overly long shebang in /home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks-admin-5.3
==> Successfully installed lua
  Fetch: 0.02s.  Build: 2.80s.  Total: 2.81s.
[+] /home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd
==> Already downloaded /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d/lua-luaposix-33.4.0.tar.gz
==> Already staged lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d in /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d
==> No patches needed for lua-luaposix
==> Building lua-luaposix
==> WRITE LOCK : /home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/.locks/lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d [Released]
==> WRITE LOCK : /home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/stage/lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d.lock [Released]
==> Error: Command exited with status 1:
'/home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks' '--tree=/home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-luaposix-33.4.0-tinxfyym6p3tdoosmd523h7jdzr2je5d' 'install' 'luaposix-33.4.0-1.rockspec'

See build log for details:
  /tmp/mculpo/spack-stage/spack-stage-XC32Fi/luaposix-release-v33.4.0/spack-build.out

/home/mculpo/PycharmProjects/spack-lafnetscha/var/spack/repos/builtin/packages/lua-luaposix/package.py:16, in install:
     14       def install(self, spec, prefix):
     15           rockspec = glob.glob('luaposix-*.rockspec')
  >> 16           luarocks('--tree=' + prefix, 'install', rockspec[0])
==> Error: Installation process had nonzero exit code.
```

In the `spack-build.out file` there's a line pointing to the problem:

```
/home/mculpo/PycharmProjects/spack-lafnetscha/opt/spack/linux-x86_64/gcc-4.8/lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/lua: .../lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks:2: unexpected symbol near '#'
```

which is the shebang at line 2 in file `../lua-5.3.2-urabougj2fmubxqmrsjrzrxk5fn6lhxd/bin/luarocks`



Discussion:

Resolving patch:
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
--- 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 re
 
 import llnl.util.tty as tty
 
@@ -57,11 +58,15 @@ def filter_shebang(path):
     if original.startswith(new_sbang_line):
         return
 
+    # Use --! instead of #! on second line for lua.
+    if re.search(r'^#!(/[^/]*)*lua\b', original):
+        original = re.sub(r'^#', '--', original)
+
     with open(path, 'w') as new_file:
         new_file.write(new_sbang_line)
         new_file.write(original)
 
-    tty.warn("Patched overly long shebang in %s" % path)
+    tty.warn("Patched overlong shebang in %s" % path)
 
 
 def filter_shebangs_in_directory(directory):


Test patch:
diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py
--- a/lib/spack/spack/test/sbang.py
+++ b/lib/spack/spack/test/sbang.py
@@ -34,10 +34,12 @@
 from spack.hooks.sbang import filter_shebangs_in_directory
 import spack
 
-short_line = "#!/this/is/short/bin/bash\n"
-long_line  = "#!/this/" + ('x' * 200) + "/is/long\n"
-sbang_line = '#!/bin/bash %s/bin/sbang\n' % spack.spack_root
-last_line = "last!\n"
+short_line       = "#!/this/is/short/bin/bash\n"
+long_line        = "#!/this/" + ('x' * 200) + "/is/long\n"
+lua_line         = "#!/this/" + ('x' * 200) + "/is/lua\n"
+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):
@@ -59,6 +61,12 @@ def setUp(self):
             f.write(long_line)
             f.write(last_line)
 
+        # Lua script with long shebang
+        self.lua_shebang = os.path.join(self.tempdir, 'lua')
+        with open(self.lua_shebang, 'w') as f:
+            f.write(lua_line)
+            f.write(last_line)
+
         # Script already using sbang.
         self.has_shebang = os.path.join(self.tempdir, 'shebang')
         with open(self.has_shebang, 'w') as f:
@@ -71,7 +79,6 @@ def tearDown(self):
          shutil.rmtree(self.tempdir, ignore_errors=True)
 
 
-
     def test_shebang_handling(self):
         filter_shebangs_in_directory(self.tempdir)
 
@@ -86,6 +93,12 @@ def test_shebang_handling(self):
             self.assertEqual(f.readline(), long_line)
             self.assertEqual(f.readline(), last_line)
 
+        # Make sure this got patched.
+        with open(self.lua_shebang, 'r') as f:
+            self.assertEqual(f.readline(), sbang_line)
+            self.assertEqual(f.readline(), lua_line_patched)
+            self.assertEqual(f.readline(), last_line)
+
         # Make sure this is untouched
         with open(self.has_shebang, 'r') as f:
             self.assertEqual(f.readline(), sbang_line)