diff options
Diffstat (limited to 'lib/spack/spack/hooks/sbang.py')
-rw-r--r-- | lib/spack/spack/hooks/sbang.py | 39 |
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) |