summaryrefslogtreecommitdiff
path: root/lib/spack/spack/hooks/sbang.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/hooks/sbang.py')
-rw-r--r--lib/spack/spack/hooks/sbang.py39
1 files changed, 35 insertions, 4 deletions
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
index b4ee0c1728..324d5d4fbb 100644
--- a/lib/spack/spack/hooks/sbang.py
+++ b/lib/spack/spack/hooks/sbang.py
@@ -3,21 +3,30 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+import filecmp
import os
import stat
import re
import sys
import llnl.util.tty as tty
+import llnl.util.filesystem as fs
-import spack.paths
import spack.modules
+import spack.paths
+import spack.store
+
-# Character limit for shebang line. Using Linux's 127 characters
-# here, as it is the shortest I could find on a modern OS.
+#: Character limit for shebang line. Using Linux's 127 characters
+#: here, as it is the shortest I could find on a modern OS.
shebang_limit = 127
+def sbang_install_path():
+ """Location sbang should be installed within Spack's ``install_tree``."""
+ return os.path.join(spack.store.layout.root, "bin", "sbang")
+
+
def shebang_too_long(path):
"""Detects whether a file has a shebang line that is too long."""
if not os.path.isfile(path):
@@ -42,7 +51,7 @@ def filter_shebang(path):
original = original.decode('UTF-8')
# This line will be prepended to file
- new_sbang_line = '#!/bin/bash %s/bin/sbang\n' % spack.paths.prefix
+ new_sbang_line = '#!/bin/bash %s\n' % sbang_install_path()
# Skip files that are already using sbang.
if original.startswith(new_sbang_line):
@@ -102,6 +111,26 @@ def filter_shebangs_in_directory(directory, filenames=None):
filter_shebang(path)
+def install_sbang():
+ """Ensure that ``sbang`` is installed in the root of Spack's install_tree.
+
+ This is the shortest known publicly accessible path, and installing
+ ``sbang`` here ensures that users can access the script and that
+ ``sbang`` itself is in a short path.
+ """
+ # copy in a new version of sbang if it differs from what's in spack
+ sbang_path = sbang_install_path()
+ if os.path.exists(sbang_path) and filecmp.cmp(
+ spack.paths.sbang_script, sbang_path):
+ return
+
+ # make $install_tree/bin and copy in a new version of sbang if needed
+ sbang_bin_dir = os.path.dirname(sbang_path)
+ fs.mkdirp(sbang_bin_dir)
+ fs.install(spack.paths.sbang_script, sbang_path)
+ fs.set_install_permissions(sbang_bin_dir)
+
+
def post_install(spec):
"""This hook edits scripts so that they call /bin/bash
$spack_prefix/bin/sbang instead of something longer than the
@@ -111,5 +140,7 @@ def post_install(spec):
tty.debug('SKIP: shebang filtering [external package]')
return
+ install_sbang()
+
for directory, _, filenames in os.walk(spec.prefix):
filter_shebangs_in_directory(directory, filenames)