We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cannot specify custom Python shebang for hook executable
I am working on a shared Python environment with `python3.6` as executable and I want the shebang to point to the correct executable `#!/usr/bin/env python3.6`. However, even though I specify 
```
default_language_version:
    python: python3.6
```
or  `language_version: python3.6` in `hooks`, it always picks `#!/usr/bin/env python` as the shebang even though there is no `python` executable. Is there a way to specify a custom shebang?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/commands/install_uninstall.py`
Content:
```
1 import itertools
2 import logging
3 import os.path
4 import shutil
5 import sys
6 from typing import Optional
7 from typing import Sequence
8 from typing import Tuple
9 
10 from pre_commit import git
11 from pre_commit import output
12 from pre_commit.clientlib import load_config
13 from pre_commit.repository import all_hooks
14 from pre_commit.repository import install_hook_envs
15 from pre_commit.store import Store
16 from pre_commit.util import make_executable
17 from pre_commit.util import resource_text
18 
19 
20 logger = logging.getLogger(__name__)
21 
22 # This is used to identify the hook file we install
23 PRIOR_HASHES = (
24     '4d9958c90bc262f47553e2c073f14cfe',
25     'd8ee923c46731b42cd95cc869add4062',
26     '49fd668cb42069aa1b6048464be5d395',
27     '79f09a650522a87b0da915d0d983b2de',
28     'e358c9dae00eac5d06b38dfdb1e33a8c',
29 )
30 CURRENT_HASH = '138fd403232d2ddd5efb44317e38bf03'
31 TEMPLATE_START = '# start templated\n'
32 TEMPLATE_END = '# end templated\n'
33 
34 
35 def _hook_paths(
36         hook_type: str,
37         git_dir: Optional[str] = None,
38 ) -> Tuple[str, str]:
39     git_dir = git_dir if git_dir is not None else git.get_git_dir()
40     pth = os.path.join(git_dir, 'hooks', hook_type)
41     return pth, f'{pth}.legacy'
42 
43 
44 def is_our_script(filename: str) -> bool:
45     if not os.path.exists(filename):  # pragma: windows no cover (symlink)
46         return False
47     with open(filename) as f:
48         contents = f.read()
49     return any(h in contents for h in (CURRENT_HASH,) + PRIOR_HASHES)
50 
51 
52 def shebang() -> str:
53     if sys.platform == 'win32':
54         py = 'python'
55     else:
56         # Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`
57         path_choices = [p for p in os.defpath.split(os.pathsep) if p]
58         exe_choices = [
59             f'python{sys.version_info[0]}.{sys.version_info[1]}',
60             f'python{sys.version_info[0]}',
61         ]
62         for path, exe in itertools.product(path_choices, exe_choices):
63             if os.access(os.path.join(path, exe), os.X_OK):
64                 py = exe
65                 break
66         else:
67             py = 'python'
68     return f'#!/usr/bin/env {py}'
69 
70 
71 def _install_hook_script(
72         config_file: str,
73         hook_type: str,
74         overwrite: bool = False,
75         skip_on_missing_config: bool = False,
76         git_dir: Optional[str] = None,
77 ) -> None:
78     hook_path, legacy_path = _hook_paths(hook_type, git_dir=git_dir)
79 
80     os.makedirs(os.path.dirname(hook_path), exist_ok=True)
81 
82     # If we have an existing hook, move it to pre-commit.legacy
83     if os.path.lexists(hook_path) and not is_our_script(hook_path):
84         shutil.move(hook_path, legacy_path)
85 
86     # If we specify overwrite, we simply delete the legacy file
87     if overwrite and os.path.exists(legacy_path):
88         os.remove(legacy_path)
89     elif os.path.exists(legacy_path):
90         output.write_line(
91             f'Running in migration mode with existing hooks at {legacy_path}\n'
92             f'Use -f to use only pre-commit.',
93         )
94 
95     args = ['hook-impl', f'--config={config_file}', f'--hook-type={hook_type}']
96     if skip_on_missing_config:
97         args.append('--skip-on-missing-config')
98     params = {'INSTALL_PYTHON': sys.executable, 'ARGS': args}
99 
100     with open(hook_path, 'w') as hook_file:
101         contents = resource_text('hook-tmpl')
102         before, rest = contents.split(TEMPLATE_START)
103         to_template, after = rest.split(TEMPLATE_END)
104 
105         before = before.replace('#!/usr/bin/env python3', shebang())
106 
107         hook_file.write(before + TEMPLATE_START)
108         for line in to_template.splitlines():
109             var = line.split()[0]
110             hook_file.write(f'{var} = {params[var]!r}\n')
111         hook_file.write(TEMPLATE_END + after)
112     make_executable(hook_path)
113 
114     output.write_line(f'pre-commit installed at {hook_path}')
115 
116 
117 def install(
118         config_file: str,
119         store: Store,
120         hook_types: Sequence[str],
121         overwrite: bool = False,
122         hooks: bool = False,
123         skip_on_missing_config: bool = False,
124         git_dir: Optional[str] = None,
125 ) -> int:
126     if git_dir is None and git.has_core_hookpaths_set():
127         logger.error(
128             'Cowardly refusing to install hooks with `core.hooksPath` set.\n'
129             'hint: `git config --unset-all core.hooksPath`',
130         )
131         return 1
132 
133     for hook_type in hook_types:
134         _install_hook_script(
135             config_file, hook_type,
136             overwrite=overwrite,
137             skip_on_missing_config=skip_on_missing_config,
138             git_dir=git_dir,
139         )
140 
141     if hooks:
142         install_hooks(config_file, store)
143 
144     return 0
145 
146 
147 def install_hooks(config_file: str, store: Store) -> int:
148     install_hook_envs(all_hooks(load_config(config_file), store), store)
149     return 0
150 
151 
152 def _uninstall_hook_script(hook_type: str) -> None:
153     hook_path, legacy_path = _hook_paths(hook_type)
154 
155     # If our file doesn't exist or it isn't ours, gtfo.
156     if not os.path.exists(hook_path) or not is_our_script(hook_path):
157         return
158 
159     os.remove(hook_path)
160     output.write_line(f'{hook_type} uninstalled')
161 
162     if os.path.exists(legacy_path):
163         os.rename(legacy_path, hook_path)
164         output.write_line(f'Restored previous hooks to {hook_path}')
165 
166 
167 def uninstall(hook_types: Sequence[str]) -> int:
168     for hook_type in hook_types:
169         _uninstall_hook_script(hook_type)
170     return 0
171
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py
--- a/pre_commit/commands/install_uninstall.py
+++ b/pre_commit/commands/install_uninstall.py
@@ -30,6 +30,10 @@
 CURRENT_HASH = '138fd403232d2ddd5efb44317e38bf03'
 TEMPLATE_START = '# start templated\n'
 TEMPLATE_END = '# end templated\n'
+# Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`
+# #1312 os.defpath is too restrictive on BSD
+POSIX_SEARCH_PATH = ('/usr/local/bin', '/usr/bin', '/bin')
+SYS_EXE = os.path.basename(os.path.realpath(sys.executable))
 
 
 def _hook_paths(
@@ -51,20 +55,21 @@
 
 def shebang() -> str:
     if sys.platform == 'win32':
-        py = 'python'
+        py = SYS_EXE
     else:
-        # Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`
-        path_choices = [p for p in os.defpath.split(os.pathsep) if p]
         exe_choices = [
             f'python{sys.version_info[0]}.{sys.version_info[1]}',
             f'python{sys.version_info[0]}',
         ]
-        for path, exe in itertools.product(path_choices, exe_choices):
+        # avoid searching for bare `python` as it's likely to be python 2
+        if SYS_EXE != 'python':
+            exe_choices.append(SYS_EXE)
+        for path, exe in itertools.product(POSIX_SEARCH_PATH, exe_choices):
             if os.access(os.path.join(path, exe), os.X_OK):
                 py = exe
                 break
         else:
-            py = 'python'
+            py = SYS_EXE
     return f'#!/usr/bin/env {py}'

{"golden_diff": "diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py\n--- a/pre_commit/commands/install_uninstall.py\n+++ b/pre_commit/commands/install_uninstall.py\n@@ -30,6 +30,10 @@\n CURRENT_HASH = '138fd403232d2ddd5efb44317e38bf03'\n TEMPLATE_START = '# start templated\\n'\n TEMPLATE_END = '# end templated\\n'\n+# Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`\n+# #1312 os.defpath is too restrictive on BSD\n+POSIX_SEARCH_PATH = ('/usr/local/bin', '/usr/bin', '/bin')\n+SYS_EXE = os.path.basename(os.path.realpath(sys.executable))\n \n \n def _hook_paths(\n@@ -51,20 +55,21 @@\n \n def shebang() -> str:\n     if sys.platform == 'win32':\n-        py = 'python'\n+        py = SYS_EXE\n     else:\n-        # Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`\n-        path_choices = [p for p in os.defpath.split(os.pathsep) if p]\n         exe_choices = [\n             f'python{sys.version_info[0]}.{sys.version_info[1]}',\n             f'python{sys.version_info[0]}',\n         ]\n-        for path, exe in itertools.product(path_choices, exe_choices):\n+        # avoid searching for bare `python` as it's likely to be python 2\n+        if SYS_EXE != 'python':\n+            exe_choices.append(SYS_EXE)\n+        for path, exe in itertools.product(POSIX_SEARCH_PATH, exe_choices):\n             if os.access(os.path.join(path, exe), os.X_OK):\n                 py = exe\n                 break\n         else:\n-            py = 'python'\n+            py = SYS_EXE\n     return f'#!/usr/bin/env {py}'\n", "issue": "Cannot specify custom Python shebang for hook executable\nI am working on a shared Python environment with `python3.6` as executable and I want the shebang to point to the correct executable `#!/usr/bin/env python3.6`. However, even though I specify \r\n```\r\ndefault_language_version:\r\n    python: python3.6\r\n```\r\nor  `language_version: python3.6` in `hooks`, it always picks `#!/usr/bin/env python` as the shebang even though there is no `python` executable. Is there a way to specify a custom shebang?\n", "before_files": [{"content": "import itertools\nimport logging\nimport os.path\nimport shutil\nimport sys\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.clientlib import load_config\nfrom pre_commit.repository import all_hooks\nfrom pre_commit.repository import install_hook_envs\nfrom pre_commit.store import Store\nfrom pre_commit.util import make_executable\nfrom pre_commit.util import resource_text\n\n\nlogger = logging.getLogger(__name__)\n\n# This is used to identify the hook file we install\nPRIOR_HASHES = (\n    '4d9958c90bc262f47553e2c073f14cfe',\n    'd8ee923c46731b42cd95cc869add4062',\n    '49fd668cb42069aa1b6048464be5d395',\n    '79f09a650522a87b0da915d0d983b2de',\n    'e358c9dae00eac5d06b38dfdb1e33a8c',\n)\nCURRENT_HASH = '138fd403232d2ddd5efb44317e38bf03'\nTEMPLATE_START = '# start templated\\n'\nTEMPLATE_END = '# end templated\\n'\n\n\ndef _hook_paths(\n        hook_type: str,\n        git_dir: Optional[str] = None,\n) -> Tuple[str, str]:\n    git_dir = git_dir if git_dir is not None else git.get_git_dir()\n    pth = os.path.join(git_dir, 'hooks', hook_type)\n    return pth, f'{pth}.legacy'\n\n\ndef is_our_script(filename: str) -> bool:\n    if not os.path.exists(filename):  # pragma: windows no cover (symlink)\n        return False\n    with open(filename) as f:\n        contents = f.read()\n    return any(h in contents for h in (CURRENT_HASH,) + PRIOR_HASHES)\n\n\ndef shebang() -> str:\n    if sys.platform == 'win32':\n        py = 'python'\n    else:\n        # Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`\n        path_choices = [p for p in os.defpath.split(os.pathsep) if p]\n        exe_choices = [\n            f'python{sys.version_info[0]}.{sys.version_info[1]}',\n            f'python{sys.version_info[0]}',\n        ]\n        for path, exe in itertools.product(path_choices, exe_choices):\n            if os.access(os.path.join(path, exe), os.X_OK):\n                py = exe\n                break\n        else:\n            py = 'python'\n    return f'#!/usr/bin/env {py}'\n\n\ndef _install_hook_script(\n        config_file: str,\n        hook_type: str,\n        overwrite: bool = False,\n        skip_on_missing_config: bool = False,\n        git_dir: Optional[str] = None,\n) -> None:\n    hook_path, legacy_path = _hook_paths(hook_type, git_dir=git_dir)\n\n    os.makedirs(os.path.dirname(hook_path), exist_ok=True)\n\n    # If we have an existing hook, move it to pre-commit.legacy\n    if os.path.lexists(hook_path) and not is_our_script(hook_path):\n        shutil.move(hook_path, legacy_path)\n\n    # If we specify overwrite, we simply delete the legacy file\n    if overwrite and os.path.exists(legacy_path):\n        os.remove(legacy_path)\n    elif os.path.exists(legacy_path):\n        output.write_line(\n            f'Running in migration mode with existing hooks at {legacy_path}\\n'\n            f'Use -f to use only pre-commit.',\n        )\n\n    args = ['hook-impl', f'--config={config_file}', f'--hook-type={hook_type}']\n    if skip_on_missing_config:\n        args.append('--skip-on-missing-config')\n    params = {'INSTALL_PYTHON': sys.executable, 'ARGS': args}\n\n    with open(hook_path, 'w') as hook_file:\n        contents = resource_text('hook-tmpl')\n        before, rest = contents.split(TEMPLATE_START)\n        to_template, after = rest.split(TEMPLATE_END)\n\n        before = before.replace('#!/usr/bin/env python3', shebang())\n\n        hook_file.write(before + TEMPLATE_START)\n        for line in to_template.splitlines():\n            var = line.split()[0]\n            hook_file.write(f'{var} = {params[var]!r}\\n')\n        hook_file.write(TEMPLATE_END + after)\n    make_executable(hook_path)\n\n    output.write_line(f'pre-commit installed at {hook_path}')\n\n\ndef install(\n        config_file: str,\n        store: Store,\n        hook_types: Sequence[str],\n        overwrite: bool = False,\n        hooks: bool = False,\n        skip_on_missing_config: bool = False,\n        git_dir: Optional[str] = None,\n) -> int:\n    if git_dir is None and git.has_core_hookpaths_set():\n        logger.error(\n            'Cowardly refusing to install hooks with `core.hooksPath` set.\\n'\n            'hint: `git config --unset-all core.hooksPath`',\n        )\n        return 1\n\n    for hook_type in hook_types:\n        _install_hook_script(\n            config_file, hook_type,\n            overwrite=overwrite,\n            skip_on_missing_config=skip_on_missing_config,\n            git_dir=git_dir,\n        )\n\n    if hooks:\n        install_hooks(config_file, store)\n\n    return 0\n\n\ndef install_hooks(config_file: str, store: Store) -> int:\n    install_hook_envs(all_hooks(load_config(config_file), store), store)\n    return 0\n\n\ndef _uninstall_hook_script(hook_type: str) -> None:\n    hook_path, legacy_path = _hook_paths(hook_type)\n\n    # If our file doesn't exist or it isn't ours, gtfo.\n    if not os.path.exists(hook_path) or not is_our_script(hook_path):\n        return\n\n    os.remove(hook_path)\n    output.write_line(f'{hook_type} uninstalled')\n\n    if os.path.exists(legacy_path):\n        os.rename(legacy_path, hook_path)\n        output.write_line(f'Restored previous hooks to {hook_path}')\n\n\ndef uninstall(hook_types: Sequence[str]) -> int:\n    for hook_type in hook_types:\n        _uninstall_hook_script(hook_type)\n    return 0\n", "path": "pre_commit/commands/install_uninstall.py"}], "after_files": [{"content": "import itertools\nimport logging\nimport os.path\nimport shutil\nimport sys\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.clientlib import load_config\nfrom pre_commit.repository import all_hooks\nfrom pre_commit.repository import install_hook_envs\nfrom pre_commit.store import Store\nfrom pre_commit.util import make_executable\nfrom pre_commit.util import resource_text\n\n\nlogger = logging.getLogger(__name__)\n\n# This is used to identify the hook file we install\nPRIOR_HASHES = (\n    '4d9958c90bc262f47553e2c073f14cfe',\n    'd8ee923c46731b42cd95cc869add4062',\n    '49fd668cb42069aa1b6048464be5d395',\n    '79f09a650522a87b0da915d0d983b2de',\n    'e358c9dae00eac5d06b38dfdb1e33a8c',\n)\nCURRENT_HASH = '138fd403232d2ddd5efb44317e38bf03'\nTEMPLATE_START = '# start templated\\n'\nTEMPLATE_END = '# end templated\\n'\n# Homebrew/homebrew-core#35825: be more timid about appropriate `PATH`\n# #1312 os.defpath is too restrictive on BSD\nPOSIX_SEARCH_PATH = ('/usr/local/bin', '/usr/bin', '/bin')\nSYS_EXE = os.path.basename(os.path.realpath(sys.executable))\n\n\ndef _hook_paths(\n        hook_type: str,\n        git_dir: Optional[str] = None,\n) -> Tuple[str, str]:\n    git_dir = git_dir if git_dir is not None else git.get_git_dir()\n    pth = os.path.join(git_dir, 'hooks', hook_type)\n    return pth, f'{pth}.legacy'\n\n\ndef is_our_script(filename: str) -> bool:\n    if not os.path.exists(filename):  # pragma: windows no cover (symlink)\n        return False\n    with open(filename) as f:\n        contents = f.read()\n    return any(h in contents for h in (CURRENT_HASH,) + PRIOR_HASHES)\n\n\ndef shebang() -> str:\n    if sys.platform == 'win32':\n        py = SYS_EXE\n    else:\n        exe_choices = [\n            f'python{sys.version_info[0]}.{sys.version_info[1]}',\n            f'python{sys.version_info[0]}',\n        ]\n        # avoid searching for bare `python` as it's likely to be python 2\n        if SYS_EXE != 'python':\n            exe_choices.append(SYS_EXE)\n        for path, exe in itertools.product(POSIX_SEARCH_PATH, exe_choices):\n            if os.access(os.path.join(path, exe), os.X_OK):\n                py = exe\n                break\n        else:\n            py = SYS_EXE\n    return f'#!/usr/bin/env {py}'\n\n\ndef _install_hook_script(\n        config_file: str,\n        hook_type: str,\n        overwrite: bool = False,\n        skip_on_missing_config: bool = False,\n        git_dir: Optional[str] = None,\n) -> None:\n    hook_path, legacy_path = _hook_paths(hook_type, git_dir=git_dir)\n\n    os.makedirs(os.path.dirname(hook_path), exist_ok=True)\n\n    # If we have an existing hook, move it to pre-commit.legacy\n    if os.path.lexists(hook_path) and not is_our_script(hook_path):\n        shutil.move(hook_path, legacy_path)\n\n    # If we specify overwrite, we simply delete the legacy file\n    if overwrite and os.path.exists(legacy_path):\n        os.remove(legacy_path)\n    elif os.path.exists(legacy_path):\n        output.write_line(\n            f'Running in migration mode with existing hooks at {legacy_path}\\n'\n            f'Use -f to use only pre-commit.',\n        )\n\n    args = ['hook-impl', f'--config={config_file}', f'--hook-type={hook_type}']\n    if skip_on_missing_config:\n        args.append('--skip-on-missing-config')\n    params = {'INSTALL_PYTHON': sys.executable, 'ARGS': args}\n\n    with open(hook_path, 'w') as hook_file:\n        contents = resource_text('hook-tmpl')\n        before, rest = contents.split(TEMPLATE_START)\n        to_template, after = rest.split(TEMPLATE_END)\n\n        before = before.replace('#!/usr/bin/env python3', shebang())\n\n        hook_file.write(before + TEMPLATE_START)\n        for line in to_template.splitlines():\n            var = line.split()[0]\n            hook_file.write(f'{var} = {params[var]!r}\\n')\n        hook_file.write(TEMPLATE_END + after)\n    make_executable(hook_path)\n\n    output.write_line(f'pre-commit installed at {hook_path}')\n\n\ndef install(\n        config_file: str,\n        store: Store,\n        hook_types: Sequence[str],\n        overwrite: bool = False,\n        hooks: bool = False,\n        skip_on_missing_config: bool = False,\n        git_dir: Optional[str] = None,\n) -> int:\n    if git_dir is None and git.has_core_hookpaths_set():\n        logger.error(\n            'Cowardly refusing to install hooks with `core.hooksPath` set.\\n'\n            'hint: `git config --unset-all core.hooksPath`',\n        )\n        return 1\n\n    for hook_type in hook_types:\n        _install_hook_script(\n            config_file, hook_type,\n            overwrite=overwrite,\n            skip_on_missing_config=skip_on_missing_config,\n            git_dir=git_dir,\n        )\n\n    if hooks:\n        install_hooks(config_file, store)\n\n    return 0\n\n\ndef install_hooks(config_file: str, store: Store) -> int:\n    install_hook_envs(all_hooks(load_config(config_file), store), store)\n    return 0\n\n\ndef _uninstall_hook_script(hook_type: str) -> None:\n    hook_path, legacy_path = _hook_paths(hook_type)\n\n    # If our file doesn't exist or it isn't ours, gtfo.\n    if not os.path.exists(hook_path) or not is_our_script(hook_path):\n        return\n\n    os.remove(hook_path)\n    output.write_line(f'{hook_type} uninstalled')\n\n    if os.path.exists(legacy_path):\n        os.rename(legacy_path, hook_path)\n        output.write_line(f'Restored previous hooks to {hook_path}')\n\n\ndef uninstall(hook_types: Sequence[str]) -> int:\n    for hook_type in hook_types:\n        _uninstall_hook_script(hook_type)\n    return 0\n", "path": "pre_commit/commands/install_uninstall.py"}]}