From bb00b1a7c9eae3d307f0a22dcccae9e33a5885d0 Mon Sep 17 00:00:00 2001
From: Toyohisa Kameyama <kameyama@riken.jp>
Date: Tue, 27 Oct 2020 14:11:43 +0900
Subject: sbang: add support for php (#18299)

PHP supports an initial shebang, but its comment syntax can't handle our 2-line
shebangs. So, we need to embed the 2nd-line shebang comment to look like a
PHP comment:

    <?php #!/path/to/php ?>

This adds patching support to the sbang hook and support for
instrumenting php shebangs.

This also patches `phar`, which is a tool used to create php packages.
`phar` itself has to add sbangs to those packages (as phar archives
apparently contain UTF-8, as well as binary blobs), and `phar` sets a
checksum based on the contents of the package.

Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
---
 lib/spack/spack/hooks/sbang.py |  4 ++++
 lib/spack/spack/test/sbang.py  | 18 ++++++++++++++++++
 2 files changed, 22 insertions(+)

(limited to 'lib')

diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
index 324d5d4fbb..24d84db8af 100644
--- a/lib/spack/spack/hooks/sbang.py
+++ b/lib/spack/spack/hooks/sbang.py
@@ -64,6 +64,10 @@ def filter_shebang(path):
     if re.search(r'^#!(/[^/\n]*)*lua\b', original):
         original = re.sub(r'^#', '--', original)
 
+    # Use <?php #! instead of #! on second line for php.
+    if re.search(r'^#!(/[^/\n]*)*php\b', original):
+        original = re.sub(r'^#', '<?php #', original) + ' ?>'
+
     # Use //! instead of #! on second line for node.js.
     if re.search(r'^#!(/[^/\n]*)*node\b', original):
         original = re.sub(r'^#', '//', original)
diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py
index eeb68f20ab..c2d0adf4d2 100644
--- a/lib/spack/spack/test/sbang.py
+++ b/lib/spack/spack/test/sbang.py
@@ -30,6 +30,11 @@ node_line         = "#!/this/" + ('x' * 200) + "/is/node\n"
 node_in_text      = ("line\n") * 100 + "lua\n" + ("line\n" * 100)
 node_line_patched = "//!/this/" + ('x' * 200) + "/is/node\n"
 sbang_line        = '#!/bin/bash %s/bin/sbang\n' % spack.store.layout.root
+php_line         = "#!/this/" + ('x' * 200) + "/is/php\n"
+php_in_text      = ("line\n") * 100 + "php\n" + ("line\n" * 100)
+php_line_patched = "<?php #!/this/" + ('x' * 200) + "/is/php\n"
+php_line_patched2 = "?>\n"
+sbang_line        = '#!/bin/bash %s/bin/sbang\n' % spack.store.layout.root
 last_line         = "last!\n"
 
 
@@ -79,6 +84,19 @@ class ScriptDirectory(object):
             f.write(node_in_text)
             f.write(last_line)
 
+        # php script with long shebang
+        self.php_shebang = os.path.join(self.tempdir, 'php')
+        with open(self.php_shebang, 'w') as f:
+            f.write(php_line)
+            f.write(last_line)
+
+        # php script with long shebang
+        self.php_textbang = os.path.join(self.tempdir, 'php_in_text')
+        with open(self.php_textbang, 'w') as f:
+            f.write(short_line)
+            f.write(php_in_text)
+            f.write(last_line)
+
         # Script already using sbang.
         self.has_sbang = os.path.join(self.tempdir, 'shebang')
         with open(self.has_sbang, 'w') as f:
-- 
cgit v1.2.3-70-g09d2