We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Empty hook file causes cryptic error
If you have a pre_gen_project.sh or a post_gen_project.sh file with no data in it, cookiecutter fails with an unhelpful traceback.

```
Traceback (most recent call last):
  File "/usr/local/bin/cookiecutter", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 716, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 696, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 889, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 534, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/cli.py", line 100, in main
    config_file=user_config
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/main.py", line 140, in cookiecutter
    output_dir=output_dir
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/generate.py", line 273, in generate_files
    _run_hook_from_repo_dir(repo_dir, 'pre_gen_project', project_dir, context)
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/generate.py", line 232, in _run_hook_from_repo_dir
    run_hook(hook_name, project_dir, context)
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py", line 116, in run_hook
    run_script_with_context(script, project_dir, context)
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py", line 101, in run_script_with_context
    run_script(temp.name, cwd)
  File "/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py", line 73, in run_script
    cwd=cwd
  File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 656, in __init__
    _cleanup()
  File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
OSError: [Errno 8] Exec format error
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cookiecutter/hooks.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 """Functions for discovering and executing various cookiecutter hooks."""
4 
5 import io
6 import logging
7 import os
8 import subprocess
9 import sys
10 import tempfile
11 
12 from jinja2 import Template
13 
14 from cookiecutter import utils
15 from .exceptions import FailedHookException
16 
17 logger = logging.getLogger(__name__)
18 
19 _HOOKS = [
20     'pre_gen_project',
21     'post_gen_project',
22 ]
23 EXIT_SUCCESS = 0
24 
25 
26 def valid_hook(hook_file, hook_name):
27     """Determine if a hook file is valid.
28 
29     :param hook_file: The hook file to consider for validity
30     :param hook_name: The hook to find
31     :return: The hook file validity
32     """
33     filename = os.path.basename(hook_file)
34     basename = os.path.splitext(filename)[0]
35 
36     matching_hook = basename == hook_name
37     supported_hook = basename in _HOOKS
38     backup_file = filename.endswith('~')
39 
40     return matching_hook and supported_hook and not backup_file
41 
42 
43 def find_hook(hook_name, hooks_dir='hooks'):
44     """Return a dict of all hook scripts provided.
45 
46     Must be called with the project template as the current working directory.
47     Dict's key will be the hook/script's name, without extension, while values
48     will be the absolute path to the script. Missing scripts will not be
49     included in the returned dict.
50 
51     :param hook_name: The hook to find
52     :param hooks_dir: The hook directory in the template
53     :return: The absolute path to the hook script or None
54     """
55     logger.debug('hooks_dir is {}'.format(os.path.abspath(hooks_dir)))
56 
57     if not os.path.isdir(hooks_dir):
58         logger.debug('No hooks/ dir in template_dir')
59         return None
60 
61     for hook_file in os.listdir(hooks_dir):
62         if valid_hook(hook_file, hook_name):
63             return os.path.abspath(os.path.join(hooks_dir, hook_file))
64 
65     return None
66 
67 
68 def run_script(script_path, cwd='.'):
69     """Execute a script from a working directory.
70 
71     :param script_path: Absolute path to the script to run.
72     :param cwd: The directory to run the script from.
73     """
74     run_thru_shell = sys.platform.startswith('win')
75     if script_path.endswith('.py'):
76         script_command = [sys.executable, script_path]
77     else:
78         script_command = [script_path]
79 
80     utils.make_executable(script_path)
81 
82     proc = subprocess.Popen(
83         script_command,
84         shell=run_thru_shell,
85         cwd=cwd
86     )
87     exit_status = proc.wait()
88     if exit_status != EXIT_SUCCESS:
89         raise FailedHookException(
90             "Hook script failed (exit status: %d)" % exit_status)
91 
92 
93 def run_script_with_context(script_path, cwd, context):
94     """Execute a script after rendering it with Jinja.
95 
96     :param script_path: Absolute path to the script to run.
97     :param cwd: The directory to run the script from.
98     :param context: Cookiecutter project template context.
99     """
100     _, extension = os.path.splitext(script_path)
101 
102     contents = io.open(script_path, 'r', encoding='utf-8').read()
103 
104     with tempfile.NamedTemporaryFile(
105         delete=False,
106         mode='wb',
107         suffix=extension
108     ) as temp:
109         output = Template(contents).render(**context)
110         temp.write(output.encode('utf-8'))
111 
112     run_script(temp.name, cwd)
113 
114 
115 def run_hook(hook_name, project_dir, context):
116     """
117     Try to find and execute a hook from the specified project directory.
118 
119     :param hook_name: The hook to execute.
120     :param project_dir: The directory to execute the script from.
121     :param context: Cookiecutter project context.
122     """
123     script = find_hook(hook_name)
124     if script is None:
125         logger.debug('No hooks found')
126         return
127     logger.debug('Running hook {}'.format(hook_name))
128     run_script_with_context(script, project_dir, context)
129
```
--- 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/cookiecutter/hooks.py b/cookiecutter/hooks.py
--- a/cookiecutter/hooks.py
+++ b/cookiecutter/hooks.py
@@ -2,6 +2,7 @@
 
 """Functions for discovering and executing various cookiecutter hooks."""
 
+import errno
 import io
 import logging
 import os
@@ -79,15 +80,26 @@
 
     utils.make_executable(script_path)
 
-    proc = subprocess.Popen(
-        script_command,
-        shell=run_thru_shell,
-        cwd=cwd
-    )
-    exit_status = proc.wait()
-    if exit_status != EXIT_SUCCESS:
+    try:
+        proc = subprocess.Popen(
+            script_command,
+            shell=run_thru_shell,
+            cwd=cwd
+        )
+        exit_status = proc.wait()
+        if exit_status != EXIT_SUCCESS:
+            raise FailedHookException(
+                'Hook script failed (exit status: {})'.format(exit_status)
+            )
+    except OSError as os_error:
+        if os_error.errno == errno.ENOEXEC:
+            raise FailedHookException(
+                'Hook script failed, might be an '
+                'empty file or missing a shebang'
+            )
         raise FailedHookException(
-            "Hook script failed (exit status: %d)" % exit_status)
+            'Hook script failed (error: {})'.format(os_error)
+        )
 
 
 def run_script_with_context(script_path, cwd, context):

{"golden_diff": "diff --git a/cookiecutter/hooks.py b/cookiecutter/hooks.py\n--- a/cookiecutter/hooks.py\n+++ b/cookiecutter/hooks.py\n@@ -2,6 +2,7 @@\n \n \"\"\"Functions for discovering and executing various cookiecutter hooks.\"\"\"\n \n+import errno\n import io\n import logging\n import os\n@@ -79,15 +80,26 @@\n \n     utils.make_executable(script_path)\n \n-    proc = subprocess.Popen(\n-        script_command,\n-        shell=run_thru_shell,\n-        cwd=cwd\n-    )\n-    exit_status = proc.wait()\n-    if exit_status != EXIT_SUCCESS:\n+    try:\n+        proc = subprocess.Popen(\n+            script_command,\n+            shell=run_thru_shell,\n+            cwd=cwd\n+        )\n+        exit_status = proc.wait()\n+        if exit_status != EXIT_SUCCESS:\n+            raise FailedHookException(\n+                'Hook script failed (exit status: {})'.format(exit_status)\n+            )\n+    except OSError as os_error:\n+        if os_error.errno == errno.ENOEXEC:\n+            raise FailedHookException(\n+                'Hook script failed, might be an '\n+                'empty file or missing a shebang'\n+            )\n         raise FailedHookException(\n-            \"Hook script failed (exit status: %d)\" % exit_status)\n+            'Hook script failed (error: {})'.format(os_error)\n+        )\n \n \n def run_script_with_context(script_path, cwd, context):\n", "issue": "Empty hook file causes cryptic error\nIf you have a pre_gen_project.sh or a post_gen_project.sh file with no data in it, cookiecutter fails with an unhelpful traceback.\n\n```\nTraceback (most recent call last):\n  File \"/usr/local/bin/cookiecutter\", line 11, in <module>\n    sys.exit(main())\n  File \"/usr/local/lib/python2.7/site-packages/click/core.py\", line 716, in __call__\n    return self.main(*args, **kwargs)\n  File \"/usr/local/lib/python2.7/site-packages/click/core.py\", line 696, in main\n    rv = self.invoke(ctx)\n  File \"/usr/local/lib/python2.7/site-packages/click/core.py\", line 889, in invoke\n    return ctx.invoke(self.callback, **ctx.params)\n  File \"/usr/local/lib/python2.7/site-packages/click/core.py\", line 534, in invoke\n    return callback(*args, **kwargs)\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/cli.py\", line 100, in main\n    config_file=user_config\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/main.py\", line 140, in cookiecutter\n    output_dir=output_dir\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/generate.py\", line 273, in generate_files\n    _run_hook_from_repo_dir(repo_dir, 'pre_gen_project', project_dir, context)\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/generate.py\", line 232, in _run_hook_from_repo_dir\n    run_hook(hook_name, project_dir, context)\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py\", line 116, in run_hook\n    run_script_with_context(script, project_dir, context)\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py\", line 101, in run_script_with_context\n    run_script(temp.name, cwd)\n  File \"/usr/local/lib/python2.7/site-packages/cookiecutter/hooks.py\", line 73, in run_script\n    cwd=cwd\n  File \"/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py\", line 656, in __init__\n    _cleanup()\n  File \"/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py\", line 1335, in _execute_child\n    raise child_exception\nOSError: [Errno 8] Exec format error\n```\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n\"\"\"Functions for discovering and executing various cookiecutter hooks.\"\"\"\n\nimport io\nimport logging\nimport os\nimport subprocess\nimport sys\nimport tempfile\n\nfrom jinja2 import Template\n\nfrom cookiecutter import utils\nfrom .exceptions import FailedHookException\n\nlogger = logging.getLogger(__name__)\n\n_HOOKS = [\n    'pre_gen_project',\n    'post_gen_project',\n]\nEXIT_SUCCESS = 0\n\n\ndef valid_hook(hook_file, hook_name):\n    \"\"\"Determine if a hook file is valid.\n\n    :param hook_file: The hook file to consider for validity\n    :param hook_name: The hook to find\n    :return: The hook file validity\n    \"\"\"\n    filename = os.path.basename(hook_file)\n    basename = os.path.splitext(filename)[0]\n\n    matching_hook = basename == hook_name\n    supported_hook = basename in _HOOKS\n    backup_file = filename.endswith('~')\n\n    return matching_hook and supported_hook and not backup_file\n\n\ndef find_hook(hook_name, hooks_dir='hooks'):\n    \"\"\"Return a dict of all hook scripts provided.\n\n    Must be called with the project template as the current working directory.\n    Dict's key will be the hook/script's name, without extension, while values\n    will be the absolute path to the script. Missing scripts will not be\n    included in the returned dict.\n\n    :param hook_name: The hook to find\n    :param hooks_dir: The hook directory in the template\n    :return: The absolute path to the hook script or None\n    \"\"\"\n    logger.debug('hooks_dir is {}'.format(os.path.abspath(hooks_dir)))\n\n    if not os.path.isdir(hooks_dir):\n        logger.debug('No hooks/ dir in template_dir')\n        return None\n\n    for hook_file in os.listdir(hooks_dir):\n        if valid_hook(hook_file, hook_name):\n            return os.path.abspath(os.path.join(hooks_dir, hook_file))\n\n    return None\n\n\ndef run_script(script_path, cwd='.'):\n    \"\"\"Execute a script from a working directory.\n\n    :param script_path: Absolute path to the script to run.\n    :param cwd: The directory to run the script from.\n    \"\"\"\n    run_thru_shell = sys.platform.startswith('win')\n    if script_path.endswith('.py'):\n        script_command = [sys.executable, script_path]\n    else:\n        script_command = [script_path]\n\n    utils.make_executable(script_path)\n\n    proc = subprocess.Popen(\n        script_command,\n        shell=run_thru_shell,\n        cwd=cwd\n    )\n    exit_status = proc.wait()\n    if exit_status != EXIT_SUCCESS:\n        raise FailedHookException(\n            \"Hook script failed (exit status: %d)\" % exit_status)\n\n\ndef run_script_with_context(script_path, cwd, context):\n    \"\"\"Execute a script after rendering it with Jinja.\n\n    :param script_path: Absolute path to the script to run.\n    :param cwd: The directory to run the script from.\n    :param context: Cookiecutter project template context.\n    \"\"\"\n    _, extension = os.path.splitext(script_path)\n\n    contents = io.open(script_path, 'r', encoding='utf-8').read()\n\n    with tempfile.NamedTemporaryFile(\n        delete=False,\n        mode='wb',\n        suffix=extension\n    ) as temp:\n        output = Template(contents).render(**context)\n        temp.write(output.encode('utf-8'))\n\n    run_script(temp.name, cwd)\n\n\ndef run_hook(hook_name, project_dir, context):\n    \"\"\"\n    Try to find and execute a hook from the specified project directory.\n\n    :param hook_name: The hook to execute.\n    :param project_dir: The directory to execute the script from.\n    :param context: Cookiecutter project context.\n    \"\"\"\n    script = find_hook(hook_name)\n    if script is None:\n        logger.debug('No hooks found')\n        return\n    logger.debug('Running hook {}'.format(hook_name))\n    run_script_with_context(script, project_dir, context)\n", "path": "cookiecutter/hooks.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n\"\"\"Functions for discovering and executing various cookiecutter hooks.\"\"\"\n\nimport errno\nimport io\nimport logging\nimport os\nimport subprocess\nimport sys\nimport tempfile\n\nfrom jinja2 import Template\n\nfrom cookiecutter import utils\nfrom .exceptions import FailedHookException\n\nlogger = logging.getLogger(__name__)\n\n_HOOKS = [\n    'pre_gen_project',\n    'post_gen_project',\n]\nEXIT_SUCCESS = 0\n\n\ndef valid_hook(hook_file, hook_name):\n    \"\"\"Determine if a hook file is valid.\n\n    :param hook_file: The hook file to consider for validity\n    :param hook_name: The hook to find\n    :return: The hook file validity\n    \"\"\"\n    filename = os.path.basename(hook_file)\n    basename = os.path.splitext(filename)[0]\n\n    matching_hook = basename == hook_name\n    supported_hook = basename in _HOOKS\n    backup_file = filename.endswith('~')\n\n    return matching_hook and supported_hook and not backup_file\n\n\ndef find_hook(hook_name, hooks_dir='hooks'):\n    \"\"\"Return a dict of all hook scripts provided.\n\n    Must be called with the project template as the current working directory.\n    Dict's key will be the hook/script's name, without extension, while values\n    will be the absolute path to the script. Missing scripts will not be\n    included in the returned dict.\n\n    :param hook_name: The hook to find\n    :param hooks_dir: The hook directory in the template\n    :return: The absolute path to the hook script or None\n    \"\"\"\n    logger.debug('hooks_dir is {}'.format(os.path.abspath(hooks_dir)))\n\n    if not os.path.isdir(hooks_dir):\n        logger.debug('No hooks/ dir in template_dir')\n        return None\n\n    for hook_file in os.listdir(hooks_dir):\n        if valid_hook(hook_file, hook_name):\n            return os.path.abspath(os.path.join(hooks_dir, hook_file))\n\n    return None\n\n\ndef run_script(script_path, cwd='.'):\n    \"\"\"Execute a script from a working directory.\n\n    :param script_path: Absolute path to the script to run.\n    :param cwd: The directory to run the script from.\n    \"\"\"\n    run_thru_shell = sys.platform.startswith('win')\n    if script_path.endswith('.py'):\n        script_command = [sys.executable, script_path]\n    else:\n        script_command = [script_path]\n\n    utils.make_executable(script_path)\n\n    try:\n        proc = subprocess.Popen(\n            script_command,\n            shell=run_thru_shell,\n            cwd=cwd\n        )\n        exit_status = proc.wait()\n        if exit_status != EXIT_SUCCESS:\n            raise FailedHookException(\n                'Hook script failed (exit status: {})'.format(exit_status)\n            )\n    except OSError as os_error:\n        if os_error.errno == errno.ENOEXEC:\n            raise FailedHookException(\n                'Hook script failed, might be an '\n                'empty file or missing a shebang'\n            )\n        raise FailedHookException(\n            'Hook script failed (error: {})'.format(os_error)\n        )\n\n\ndef run_script_with_context(script_path, cwd, context):\n    \"\"\"Execute a script after rendering it with Jinja.\n\n    :param script_path: Absolute path to the script to run.\n    :param cwd: The directory to run the script from.\n    :param context: Cookiecutter project template context.\n    \"\"\"\n    _, extension = os.path.splitext(script_path)\n\n    contents = io.open(script_path, 'r', encoding='utf-8').read()\n\n    with tempfile.NamedTemporaryFile(\n        delete=False,\n        mode='wb',\n        suffix=extension\n    ) as temp:\n        output = Template(contents).render(**context)\n        temp.write(output.encode('utf-8'))\n\n    run_script(temp.name, cwd)\n\n\ndef run_hook(hook_name, project_dir, context):\n    \"\"\"\n    Try to find and execute a hook from the specified project directory.\n\n    :param hook_name: The hook to execute.\n    :param project_dir: The directory to execute the script from.\n    :param context: Cookiecutter project context.\n    \"\"\"\n    script = find_hook(hook_name)\n    if script is None:\n        logger.debug('No hooks found')\n        return\n    logger.debug('Running hook {}'.format(hook_name))\n    run_script_with_context(script, project_dir, context)\n", "path": "cookiecutter/hooks.py"}]}