Repository: pypa/virtualenv

Issue:
Custom bootstrap script does not contain extra_text
Below is how to create custom bootstrap script.
https://virtualenv.pypa.io/en/latest/reference/#creating-your-own-bootstrap-scripts

But created script does not contain extra_text with virtualenv 16.1.0 and master.

```
$ python -c "import virtualenv; print(virtualenv.create_bootstrap_script('HELLOWORLD'))"| grep HELLOWORLD
$
```

Seems expected bootstrap script can be created with virtualenv 16.0.0
```
$ python -c "import virtualenv; print(virtualenv.create_bootstrap_script('HELLOWORLD'))"| grep HELLOWORLD
HELLOWORLD
$
```



Discussion:
Thanks for this report, I'll address this.

Resolving patch:
diff --git a/virtualenv.py b/virtualenv.py
--- a/virtualenv.py
+++ b/virtualenv.py
@@ -1881,6 +1881,9 @@ def make_relative_path(source, dest, dest_is_directory=True):
     return os.path.sep.join(full_parts)
 
 
+FILE_PATH = __file__ if os.path.isabs(__file__) else os.path.join(os.getcwd(), __file__)
+
+
 # Bootstrap script creation:
 def create_bootstrap_script(extra_text, python_version=""):
     """
@@ -1922,17 +1925,20 @@ def after_install(options, home_dir):
     ``#!/usr/bin/env python``.  You can use this when the script must
     be run with a particular Python version.
     """
-    filename = __file__
+    filename = FILE_PATH
     if filename.endswith(".pyc"):
         filename = filename[:-1]
     with codecs.open(filename, "r", encoding="utf-8") as f:
         content = f.read()
     py_exe = "python{}".format(python_version)
     content = "#!/usr/bin/env {}\n# WARNING: This file is generated\n{}".format(py_exe, content)
-    return content.replace("##EXT" "END##", extra_text)
+    # we build the string as two, to avoid replacing here, but yes further done
+    return content.replace("# EXTEND - " "bootstrap here", extra_text)
+
+
+# EXTEND - bootstrap here
 
 
-# EXTEND
 def convert(s):
     b = base64.b64decode(s.encode("ascii"))
     return zlib.decompress(b).decode("utf-8")
@@ -2429,7 +2435,3 @@ def do_file(file, offset=0, size=maxint):
 
 if __name__ == "__main__":
     main()
-
-# TODO:
-# Copy python.exe.manifest
-# Monkeypatch distutils.sysconfig


Test patch:
diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py
new file mode 100644
--- /dev/null
+++ b/tests/test_bootstrap.py
@@ -0,0 +1,87 @@
+from __future__ import absolute_import, unicode_literals
+
+import inspect
+import os
+import re
+import subprocess
+import sys
+import textwrap
+
+import six
+
+import virtualenv
+
+
+def bootstrap():
+    print("startup")
+    import subprocess
+    import os
+
+    # noinspection PyUnusedLocal
+    def extend_parser(opt_parse_parser):
+        print("extend parser with count")
+        opt_parse_parser.add_option("-c", action="count", dest="count", default=0, help="Count number of times passed")
+
+    # noinspection PyUnusedLocal
+    def adjust_options(options, args):
+        print("adjust options")
+        options.count += 1
+
+    # noinspection PyUnusedLocal
+    def after_install(options, home_dir):
+        print("after install {} with options {}".format(home_dir, options.count))
+        # noinspection PyUnresolvedReferences
+        _, _, _, bin_dir = path_locations(home_dir)  # noqa: F821
+        # noinspection PyUnresolvedReferences
+        print(
+            "exe at {}".format(
+                subprocess.check_output(
+                    [os.path.join(bin_dir, EXPECTED_EXE), "-c", "import sys; print(sys.executable)"],  # noqa: F821
+                    universal_newlines=True,
+                )
+            )
+        )
+
+
+def test_bootstrap(tmp_path, monkeypatch):
+    monkeypatch.chdir(tmp_path)
+
+    extra_code = inspect.getsource(bootstrap)
+    extra_code = textwrap.dedent(extra_code[extra_code.index("\n") + 1 :])
+
+    output = virtualenv.create_bootstrap_script(extra_code)
+    assert extra_code in output
+    if six.PY2:
+        output = output.decode()
+    write_at = tmp_path / "blog-bootstrap.py"
+    write_at.write_text(output)
+
+    try:
+        monkeypatch.chdir(tmp_path)
+        cmd = [
+            sys.executable,
+            str(write_at),
+            "--no-download",
+            "--no-pip",
+            "--no-wheel",
+            "--no-setuptools",
+            "-ccc",
+            "-qqq",
+            "env",
+        ]
+        raw = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
+        out = re.sub(r"pydev debugger: process \d+ is connecting\n\n", "", raw, re.M).strip().split("\n")
+
+        _, _, _, bin_dir = virtualenv.path_locations(str(tmp_path / "env"))
+        exe = os.path.realpath(
+            os.path.join(bin_dir, "{}{}".format(virtualenv.EXPECTED_EXE, ".exe" if virtualenv.IS_WIN else ""))
+        )
+        assert out == [
+            "startup",
+            "extend parser with count",
+            "adjust options",
+            "after install env with options 4",
+            "exe at {}".format(exe),
+        ]
+    except subprocess.CalledProcessError as exception:
+        assert not exception.returncode, exception.output