Repository: spack/spack

Issue:
Patch shebang error from perl module
Building Perl with a long path breaks in my centos 7 box. The same package succeeded without the long path.

```
./bin/spack install perl
==> Installing perl
==> Trying to fetch from file:///home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/cache/perl/perl-5.24.0.tar.gz
######################################################################## 100.0%
==> Trying to fetch from file:///home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/cache/perl/App-cpanminus-1.7042.tar.gz
######################################################################## 100.0%
==> Staging archive: /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/perl-5.24.0.tar.gz
==> Created stage in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42
==> Staging archive: /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42/App-cpanminus-1.7042.tar.gz
==> Created stage in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42
==> Moving resource stage
        source : /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42/App-cpanminus-1.7042/
        destination : /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/perl-5.24.0/cpanm/cpanm
==> No patches needed for perl
==> Building perl
==> Warning: Module file already exists : skipping creation
file : /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/share/spack/dotkit/linux-centos7-x86_64/perl-5.24.0-gcc-4.8.5-kn4hndj.dk
spec : perl@5.24.0%gcc@4.8.5+cpanm arch=linux-centos7-x86_64
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/pod2man
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/pod2text
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/pod2usage
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/podchecker
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/podselect
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/c2ph
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/cpan
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/corelist
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/enc2xs
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/encguess
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/h2ph
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/h2xs
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/instmodsh
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/json_pp
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/libnetcfg
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/perlbug
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/perldoc
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/perlivp
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/piconv
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/pl2pm
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/pod2html
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/prove
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/ptar
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/ptardiff
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/ptargrep
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/shasum
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/splain
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/xsubpp
==> Warning: Patched overlong shebang in /home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/zipdetails
Traceback (most recent call last):
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/build_environment.py", line 512, in fork
    function()
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/package.py", line 1028, in build_process
    spack.hooks.post_install(self)
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/hooks/__init__.py", line 69, in __call__
    hook(pkg)
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/hooks/sbang.py", line 97, in post_install
    filter_shebangs_in_directory(pkg.prefix.bin)
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/hooks/sbang.py", line 88, in filter_shebangs_in_directory
    filter_shebang(path)
  File "/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/lib/spack/spack/hooks/sbang.py", line 65, in filter_shebang
    with open(path, 'w') as new_file:
IOError: [Errno 13] Permission denied: '/home/vagrant/myveryloooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin/cpanm'
==> Error: Installation process had nonzero exit code : 256
```

```
./bin/spack install perl
==> Installing perl
==> Trying to fetch from file:///home/vagrant/spack/var/spack/cache/perl/perl-5.24.0.tar.gz
######################################################################## 100.0%
==> Trying to fetch from file:///home/vagrant/spack/var/spack/cache/perl/App-cpanminus-1.7042.tar.gz
######################################################################## 100.0%
==> Staging archive: /home/vagrant/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/perl-5.24.0.tar.gz
==> Created stage in /home/vagrant/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42
==> Staging archive: /home/vagrant/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42/App-cpanminus-1.7042.tar.gz
==> Created stage in /home/vagrant/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42
==> Moving resource stage
        source : /home/vagrant/spack/var/spack/stage/resource-cpanm-kn4hndjc5ieonorqtgyvc4g5j4e22d42/App-cpanminus-1.7042/
        destination : /home/vagrant/spack/var/spack/stage/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/perl-5.24.0/cpanm/cpanm
==> No patches needed for perl
==> Building perl
==> Warning: Module file already exists : skipping creation
file : /home/vagrant/spack/share/spack/dotkit/linux-centos7-x86_64/perl-5.24.0-gcc-4.8.5-kn4hndj.dk
spec : perl@5.24.0%gcc@4.8.5+cpanm arch=linux-centos7-x86_64
==> Successfully installed perl
  Fetch: 0.28s.  Build: 2m 16.89s.  Total: 2m 17.18s.
[+] /home/vagrant/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42
```



Discussion:
I am not sure why this fails.  It's attempting to instrument cpanm with our `sbang` fix after installation, but it's not a logic error from that code -- it gets permission denied.  Can you run the erroneous install again with `spack install --keep-prefix`, and look at `cpanm` in the perl install directory to see why it might be failing?

``` bash
ls -algh /home/vagrant/myveryloooooooooooooooooooooooooooooooooooooooooooooongname/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/perl-5.24.0-kn4hndjc5ieonorqtgyvc4g5j4e22d42/bin
total 4.6M
drwxr-xr-x. 2 vagrant 4.0K Aug  3 16:05 .
drwxrwxr-x. 6 vagrant   49 Aug  3 16:05 ..
-rwxr-xr-x. 2 vagrant  37K Aug  3 16:05 c2ph
-rwxr-xr-x. 1 vagrant  13K Aug  3 16:05 corelist
-rwxr-xr-x. 1 vagrant 7.7K Aug  3 16:05 cpan
-r-xr-xr-x. 1 vagrant 298K Aug  3 16:05 cpanm
-rwxr-xr-x. 1 vagrant  41K Aug  3 16:05 enc2xs
-rwxr-xr-x. 1 vagrant 3.4K Aug  3 16:05 encguess
-rwxr-xr-x. 1 vagrant  29K Aug  3 16:05 h2ph
-rwxr-xr-x. 1 vagrant  60K Aug  3 16:05 h2xs
-rwxr-xr-x. 1 vagrant 4.6K Aug  3 16:05 instmodsh
-rwxr-xr-x. 1 vagrant 4.3K Aug  3 16:05 json_pp
-rwxr-xr-x. 1 vagrant  16K Aug  3 16:05 libnetcfg
-rwxr-xr-x. 2 vagrant 1.9M Aug  3 16:05 perl
-rwxr-xr-x. 2 vagrant 1.9M Aug  3 16:05 perl5.24.0
-rwxr-xr-x. 2 vagrant  45K Aug  3 16:05 perlbug
-rwxr-xr-x. 1 vagrant  648 Aug  3 16:05 perldoc
-rwxr-xr-x. 1 vagrant  12K Aug  3 16:05 perlivp
-rwxr-xr-x. 2 vagrant  45K Aug  3 16:05 perlthanks
-rwxr-xr-x. 1 vagrant 8.6K Aug  3 16:05 piconv
-rwxr-xr-x. 1 vagrant 4.9K Aug  3 16:05 pl2pm
-rwxr-xr-x. 1 vagrant 4.5K Aug  3 16:05 pod2html
-rwxr-xr-x. 1 vagrant  15K Aug  3 16:05 pod2man
-rwxr-xr-x. 1 vagrant  12K Aug  3 16:05 pod2text
-rwxr-xr-x. 1 vagrant 4.2K Aug  3 16:05 pod2usage
-rwxr-xr-x. 1 vagrant 3.9K Aug  3 16:05 podchecker
-rwxr-xr-x. 1 vagrant 2.8K Aug  3 16:05 podselect
-rwxr-xr-x. 1 vagrant  14K Aug  3 16:05 prove
-rwxr-xr-x. 2 vagrant  37K Aug  3 16:05 pstruct
-rwxr-xr-x. 1 vagrant 3.9K Aug  3 16:05 ptar
-rwxr-xr-x. 1 vagrant 3.0K Aug  3 16:05 ptardiff
-rwxr-xr-x. 1 vagrant 4.7K Aug  3 16:05 ptargrep
-rwxr-xr-x. 1 vagrant 9.6K Aug  3 16:05 shasum
-rwxr-xr-x. 1 vagrant  19K Aug  3 16:05 splain
-rwxr-xr-x. 1 vagrant 5.5K Aug  3 16:05 xsubpp
-rwxr-xr-x. 1 vagrant  48K Aug  3 16:05 zipdetails
```

perl~cpanm spec succeeds, so perl itself doesn't cause any other problems in my build. filter_shebang() in lib/spack/spack/hooks/sbang.py doesn't check if the file is writable before trying to fix the shebang. I suggest the correct fix would be for it  to set write permissions, make the change, and restore permissions.


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 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)
 
 


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
@@ -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 @@
 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 @@ def setUp(self):
             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 @@ def test_shebang_handling(self):
             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))