We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deprecate `pcre` language
Now that pygrep (#630) is a much more portable alternative, pcre is unnecessary and should be deprecated.

A deprecation warning should be issued when loading a configuration containing `language: pcre` and should point the consumer in the right direction to correcting it (either by suggesting a pull request, or by indicating they should modify their `local` configuration).

The `pcre` language will likely be removed in `pre-commit==2.0.0`

--- 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/run.py`
Content:
```
1 from __future__ import print_function
2 from __future__ import unicode_literals
3 
4 import logging
5 import os
6 import re
7 import subprocess
8 import sys
9 
10 from identify.identify import tags_from_path
11 
12 from pre_commit import color
13 from pre_commit import git
14 from pre_commit import output
15 from pre_commit.output import get_hook_message
16 from pre_commit.staged_files_only import staged_files_only
17 from pre_commit.util import cmd_output
18 from pre_commit.util import memoize_by_cwd
19 from pre_commit.util import noop_context
20 
21 
22 logger = logging.getLogger('pre_commit')
23 
24 
25 tags_from_path = memoize_by_cwd(tags_from_path)
26 
27 
28 def _get_skips(environ):
29     skips = environ.get('SKIP', '')
30     return {skip.strip() for skip in skips.split(',') if skip.strip()}
31 
32 
33 def _hook_msg_start(hook, verbose):
34     return '{}{}'.format(
35         '[{}] '.format(hook['id']) if verbose else '', hook['name'],
36     )
37 
38 
39 def _filter_by_include_exclude(filenames, include, exclude):
40     include_re, exclude_re = re.compile(include), re.compile(exclude)
41     return {
42         filename for filename in filenames
43         if (
44             include_re.search(filename) and
45             not exclude_re.search(filename) and
46             os.path.lexists(filename)
47         )
48     }
49 
50 
51 def _filter_by_types(filenames, types, exclude_types):
52     types, exclude_types = frozenset(types), frozenset(exclude_types)
53     ret = []
54     for filename in filenames:
55         tags = tags_from_path(filename)
56         if tags >= types and not tags & exclude_types:
57             ret.append(filename)
58     return tuple(ret)
59 
60 
61 SKIPPED = 'Skipped'
62 NO_FILES = '(no files to check)'
63 
64 
65 def _run_single_hook(filenames, hook, repo, args, skips, cols):
66     include, exclude = hook['files'], hook['exclude']
67     filenames = _filter_by_include_exclude(filenames, include, exclude)
68     types, exclude_types = hook['types'], hook['exclude_types']
69     filenames = _filter_by_types(filenames, types, exclude_types)
70     if hook['id'] in skips:
71         output.write(get_hook_message(
72             _hook_msg_start(hook, args.verbose),
73             end_msg=SKIPPED,
74             end_color=color.YELLOW,
75             use_color=args.color,
76             cols=cols,
77         ))
78         return 0
79     elif not filenames and not hook['always_run']:
80         output.write(get_hook_message(
81             _hook_msg_start(hook, args.verbose),
82             postfix=NO_FILES,
83             end_msg=SKIPPED,
84             end_color=color.TURQUOISE,
85             use_color=args.color,
86             cols=cols,
87         ))
88         return 0
89 
90     # Print the hook and the dots first in case the hook takes hella long to
91     # run.
92     output.write(get_hook_message(
93         _hook_msg_start(hook, args.verbose), end_len=6, cols=cols,
94     ))
95     sys.stdout.flush()
96 
97     diff_before = cmd_output(
98         'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,
99     )
100     retcode, stdout, stderr = repo.run_hook(
101         hook, tuple(filenames) if hook['pass_filenames'] else (),
102     )
103     diff_after = cmd_output(
104         'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,
105     )
106 
107     file_modifications = diff_before != diff_after
108 
109     # If the hook makes changes, fail the commit
110     if file_modifications:
111         retcode = 1
112 
113     if retcode:
114         retcode = 1
115         print_color = color.RED
116         pass_fail = 'Failed'
117     else:
118         retcode = 0
119         print_color = color.GREEN
120         pass_fail = 'Passed'
121 
122     output.write_line(color.format_color(pass_fail, print_color, args.color))
123 
124     if (stdout or stderr or file_modifications) and (retcode or args.verbose):
125         output.write_line('hookid: {}\n'.format(hook['id']))
126 
127         # Print a message if failing due to file modifications
128         if file_modifications:
129             output.write('Files were modified by this hook.')
130 
131             if stdout or stderr:
132                 output.write_line(' Additional output:')
133 
134             output.write_line()
135 
136         for out in (stdout, stderr):
137             assert type(out) is bytes, type(out)
138             if out.strip():
139                 output.write_line(out.strip(), logfile_name=hook['log_file'])
140         output.write_line()
141 
142     return retcode
143 
144 
145 def _compute_cols(hooks, verbose):
146     """Compute the number of columns to display hook messages.  The widest
147     that will be displayed is in the no files skipped case:
148 
149         Hook name...(no files to check) Skipped
150 
151     or in the verbose case
152 
153         Hook name [hookid]...(no files to check) Skipped
154     """
155     if hooks:
156         name_len = max(len(_hook_msg_start(hook, verbose)) for hook in hooks)
157     else:
158         name_len = 0
159 
160     cols = name_len + 3 + len(NO_FILES) + 1 + len(SKIPPED)
161     return max(cols, 80)
162 
163 
164 def _all_filenames(args):
165     if args.origin and args.source:
166         return git.get_changed_files(args.origin, args.source)
167     elif args.hook_stage == 'commit-msg':
168         return (args.commit_msg_filename,)
169     elif args.files:
170         return args.files
171     elif args.all_files:
172         return git.get_all_files()
173     elif git.is_in_merge_conflict():
174         return git.get_conflicted_files()
175     else:
176         return git.get_staged_files()
177 
178 
179 def _run_hooks(config, repo_hooks, args, environ):
180     """Actually run the hooks."""
181     skips = _get_skips(environ)
182     cols = _compute_cols([hook for _, hook in repo_hooks], args.verbose)
183     filenames = _all_filenames(args)
184     filenames = _filter_by_include_exclude(filenames, '', config['exclude'])
185     retval = 0
186     for repo, hook in repo_hooks:
187         retval |= _run_single_hook(filenames, hook, repo, args, skips, cols)
188         if retval and config['fail_fast']:
189             break
190     if (
191             retval and
192             args.show_diff_on_failure and
193             subprocess.call(('git', 'diff', '--quiet', '--no-ext-diff')) != 0
194     ):
195         print('All changes made by hooks:')
196         subprocess.call(('git', '--no-pager', 'diff', '--no-ext-diff'))
197     return retval
198 
199 
200 def _has_unmerged_paths():
201     _, stdout, _ = cmd_output('git', 'ls-files', '--unmerged')
202     return bool(stdout.strip())
203 
204 
205 def _has_unstaged_config(runner):
206     retcode, _, _ = cmd_output(
207         'git', 'diff', '--no-ext-diff', '--exit-code', runner.config_file_path,
208         retcode=None,
209     )
210     # be explicit, other git errors don't mean it has an unstaged config.
211     return retcode == 1
212 
213 
214 def run(runner, args, environ=os.environ):
215     no_stash = args.all_files or bool(args.files)
216 
217     # Check if we have unresolved merge conflict files and fail fast.
218     if _has_unmerged_paths():
219         logger.error('Unmerged files.  Resolve before committing.')
220         return 1
221     if bool(args.source) != bool(args.origin):
222         logger.error('Specify both --origin and --source.')
223         return 1
224     if _has_unstaged_config(runner) and not no_stash:
225         logger.error(
226             'Your pre-commit configuration is unstaged.\n'
227             '`git add {}` to fix this.'.format(runner.config_file),
228         )
229         return 1
230 
231     # Expose origin / source as environment variables for hooks to consume
232     if args.origin and args.source:
233         environ['PRE_COMMIT_ORIGIN'] = args.origin
234         environ['PRE_COMMIT_SOURCE'] = args.source
235 
236     if no_stash:
237         ctx = noop_context()
238     else:
239         ctx = staged_files_only(runner.store.directory)
240 
241     with ctx:
242         repo_hooks = []
243         for repo in runner.repositories:
244             for _, hook in repo.hooks:
245                 if (
246                     (not args.hook or hook['id'] == args.hook) and
247                     not hook['stages'] or args.hook_stage in hook['stages']
248                 ):
249                     repo_hooks.append((repo, hook))
250 
251         if args.hook and not repo_hooks:
252             output.write_line('No hook with id `{}`'.format(args.hook))
253             return 1
254 
255         for repo in {repo for repo, _ in repo_hooks}:
256             repo.require_installed()
257 
258         return _run_hooks(runner.config, repo_hooks, args, environ)
259
```
--- 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/run.py b/pre_commit/commands/run.py
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -67,6 +67,15 @@
     filenames = _filter_by_include_exclude(filenames, include, exclude)
     types, exclude_types = hook['types'], hook['exclude_types']
     filenames = _filter_by_types(filenames, types, exclude_types)
+
+    if hook['language'] == 'pcre':
+        logger.warning(
+            '`{}` (from {}) uses the deprecated pcre language.\n'
+            'The pcre language is scheduled for removal in pre-commit 2.x.\n'
+            'The pygrep language is a more portable (and usually drop-in) '
+            'replacement.'.format(hook['id'], repo.repo_config['repo']),
+        )
+
     if hook['id'] in skips:
         output.write(get_hook_message(
             _hook_msg_start(hook, args.verbose),

{"golden_diff": "diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py\n--- a/pre_commit/commands/run.py\n+++ b/pre_commit/commands/run.py\n@@ -67,6 +67,15 @@\n     filenames = _filter_by_include_exclude(filenames, include, exclude)\n     types, exclude_types = hook['types'], hook['exclude_types']\n     filenames = _filter_by_types(filenames, types, exclude_types)\n+\n+    if hook['language'] == 'pcre':\n+        logger.warning(\n+            '`{}` (from {}) uses the deprecated pcre language.\\n'\n+            'The pcre language is scheduled for removal in pre-commit 2.x.\\n'\n+            'The pygrep language is a more portable (and usually drop-in) '\n+            'replacement.'.format(hook['id'], repo.repo_config['repo']),\n+        )\n+\n     if hook['id'] in skips:\n         output.write(get_hook_message(\n             _hook_msg_start(hook, args.verbose),\n", "issue": "Deprecate `pcre` language\nNow that pygrep (#630) is a much more portable alternative, pcre is unnecessary and should be deprecated.\r\n\r\nA deprecation warning should be issued when loading a configuration containing `language: pcre` and should point the consumer in the right direction to correcting it (either by suggesting a pull request, or by indicating they should modify their `local` configuration).\r\n\r\nThe `pcre` language will likely be removed in `pre-commit==2.0.0`\n", "before_files": [{"content": "from __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport logging\nimport os\nimport re\nimport subprocess\nimport sys\n\nfrom identify.identify import tags_from_path\n\nfrom pre_commit import color\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.output import get_hook_message\nfrom pre_commit.staged_files_only import staged_files_only\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import memoize_by_cwd\nfrom pre_commit.util import noop_context\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ntags_from_path = memoize_by_cwd(tags_from_path)\n\n\ndef _get_skips(environ):\n    skips = environ.get('SKIP', '')\n    return {skip.strip() for skip in skips.split(',') if skip.strip()}\n\n\ndef _hook_msg_start(hook, verbose):\n    return '{}{}'.format(\n        '[{}] '.format(hook['id']) if verbose else '', hook['name'],\n    )\n\n\ndef _filter_by_include_exclude(filenames, include, exclude):\n    include_re, exclude_re = re.compile(include), re.compile(exclude)\n    return {\n        filename for filename in filenames\n        if (\n            include_re.search(filename) and\n            not exclude_re.search(filename) and\n            os.path.lexists(filename)\n        )\n    }\n\n\ndef _filter_by_types(filenames, types, exclude_types):\n    types, exclude_types = frozenset(types), frozenset(exclude_types)\n    ret = []\n    for filename in filenames:\n        tags = tags_from_path(filename)\n        if tags >= types and not tags & exclude_types:\n            ret.append(filename)\n    return tuple(ret)\n\n\nSKIPPED = 'Skipped'\nNO_FILES = '(no files to check)'\n\n\ndef _run_single_hook(filenames, hook, repo, args, skips, cols):\n    include, exclude = hook['files'], hook['exclude']\n    filenames = _filter_by_include_exclude(filenames, include, exclude)\n    types, exclude_types = hook['types'], hook['exclude_types']\n    filenames = _filter_by_types(filenames, types, exclude_types)\n    if hook['id'] in skips:\n        output.write(get_hook_message(\n            _hook_msg_start(hook, args.verbose),\n            end_msg=SKIPPED,\n            end_color=color.YELLOW,\n            use_color=args.color,\n            cols=cols,\n        ))\n        return 0\n    elif not filenames and not hook['always_run']:\n        output.write(get_hook_message(\n            _hook_msg_start(hook, args.verbose),\n            postfix=NO_FILES,\n            end_msg=SKIPPED,\n            end_color=color.TURQUOISE,\n            use_color=args.color,\n            cols=cols,\n        ))\n        return 0\n\n    # Print the hook and the dots first in case the hook takes hella long to\n    # run.\n    output.write(get_hook_message(\n        _hook_msg_start(hook, args.verbose), end_len=6, cols=cols,\n    ))\n    sys.stdout.flush()\n\n    diff_before = cmd_output(\n        'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,\n    )\n    retcode, stdout, stderr = repo.run_hook(\n        hook, tuple(filenames) if hook['pass_filenames'] else (),\n    )\n    diff_after = cmd_output(\n        'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,\n    )\n\n    file_modifications = diff_before != diff_after\n\n    # If the hook makes changes, fail the commit\n    if file_modifications:\n        retcode = 1\n\n    if retcode:\n        retcode = 1\n        print_color = color.RED\n        pass_fail = 'Failed'\n    else:\n        retcode = 0\n        print_color = color.GREEN\n        pass_fail = 'Passed'\n\n    output.write_line(color.format_color(pass_fail, print_color, args.color))\n\n    if (stdout or stderr or file_modifications) and (retcode or args.verbose):\n        output.write_line('hookid: {}\\n'.format(hook['id']))\n\n        # Print a message if failing due to file modifications\n        if file_modifications:\n            output.write('Files were modified by this hook.')\n\n            if stdout or stderr:\n                output.write_line(' Additional output:')\n\n            output.write_line()\n\n        for out in (stdout, stderr):\n            assert type(out) is bytes, type(out)\n            if out.strip():\n                output.write_line(out.strip(), logfile_name=hook['log_file'])\n        output.write_line()\n\n    return retcode\n\n\ndef _compute_cols(hooks, verbose):\n    \"\"\"Compute the number of columns to display hook messages.  The widest\n    that will be displayed is in the no files skipped case:\n\n        Hook name...(no files to check) Skipped\n\n    or in the verbose case\n\n        Hook name [hookid]...(no files to check) Skipped\n    \"\"\"\n    if hooks:\n        name_len = max(len(_hook_msg_start(hook, verbose)) for hook in hooks)\n    else:\n        name_len = 0\n\n    cols = name_len + 3 + len(NO_FILES) + 1 + len(SKIPPED)\n    return max(cols, 80)\n\n\ndef _all_filenames(args):\n    if args.origin and args.source:\n        return git.get_changed_files(args.origin, args.source)\n    elif args.hook_stage == 'commit-msg':\n        return (args.commit_msg_filename,)\n    elif args.files:\n        return args.files\n    elif args.all_files:\n        return git.get_all_files()\n    elif git.is_in_merge_conflict():\n        return git.get_conflicted_files()\n    else:\n        return git.get_staged_files()\n\n\ndef _run_hooks(config, repo_hooks, args, environ):\n    \"\"\"Actually run the hooks.\"\"\"\n    skips = _get_skips(environ)\n    cols = _compute_cols([hook for _, hook in repo_hooks], args.verbose)\n    filenames = _all_filenames(args)\n    filenames = _filter_by_include_exclude(filenames, '', config['exclude'])\n    retval = 0\n    for repo, hook in repo_hooks:\n        retval |= _run_single_hook(filenames, hook, repo, args, skips, cols)\n        if retval and config['fail_fast']:\n            break\n    if (\n            retval and\n            args.show_diff_on_failure and\n            subprocess.call(('git', 'diff', '--quiet', '--no-ext-diff')) != 0\n    ):\n        print('All changes made by hooks:')\n        subprocess.call(('git', '--no-pager', 'diff', '--no-ext-diff'))\n    return retval\n\n\ndef _has_unmerged_paths():\n    _, stdout, _ = cmd_output('git', 'ls-files', '--unmerged')\n    return bool(stdout.strip())\n\n\ndef _has_unstaged_config(runner):\n    retcode, _, _ = cmd_output(\n        'git', 'diff', '--no-ext-diff', '--exit-code', runner.config_file_path,\n        retcode=None,\n    )\n    # be explicit, other git errors don't mean it has an unstaged config.\n    return retcode == 1\n\n\ndef run(runner, args, environ=os.environ):\n    no_stash = args.all_files or bool(args.files)\n\n    # Check if we have unresolved merge conflict files and fail fast.\n    if _has_unmerged_paths():\n        logger.error('Unmerged files.  Resolve before committing.')\n        return 1\n    if bool(args.source) != bool(args.origin):\n        logger.error('Specify both --origin and --source.')\n        return 1\n    if _has_unstaged_config(runner) and not no_stash:\n        logger.error(\n            'Your pre-commit configuration is unstaged.\\n'\n            '`git add {}` to fix this.'.format(runner.config_file),\n        )\n        return 1\n\n    # Expose origin / source as environment variables for hooks to consume\n    if args.origin and args.source:\n        environ['PRE_COMMIT_ORIGIN'] = args.origin\n        environ['PRE_COMMIT_SOURCE'] = args.source\n\n    if no_stash:\n        ctx = noop_context()\n    else:\n        ctx = staged_files_only(runner.store.directory)\n\n    with ctx:\n        repo_hooks = []\n        for repo in runner.repositories:\n            for _, hook in repo.hooks:\n                if (\n                    (not args.hook or hook['id'] == args.hook) and\n                    not hook['stages'] or args.hook_stage in hook['stages']\n                ):\n                    repo_hooks.append((repo, hook))\n\n        if args.hook and not repo_hooks:\n            output.write_line('No hook with id `{}`'.format(args.hook))\n            return 1\n\n        for repo in {repo for repo, _ in repo_hooks}:\n            repo.require_installed()\n\n        return _run_hooks(runner.config, repo_hooks, args, environ)\n", "path": "pre_commit/commands/run.py"}], "after_files": [{"content": "from __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport logging\nimport os\nimport re\nimport subprocess\nimport sys\n\nfrom identify.identify import tags_from_path\n\nfrom pre_commit import color\nfrom pre_commit import git\nfrom pre_commit import output\nfrom pre_commit.output import get_hook_message\nfrom pre_commit.staged_files_only import staged_files_only\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import memoize_by_cwd\nfrom pre_commit.util import noop_context\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ntags_from_path = memoize_by_cwd(tags_from_path)\n\n\ndef _get_skips(environ):\n    skips = environ.get('SKIP', '')\n    return {skip.strip() for skip in skips.split(',') if skip.strip()}\n\n\ndef _hook_msg_start(hook, verbose):\n    return '{}{}'.format(\n        '[{}] '.format(hook['id']) if verbose else '', hook['name'],\n    )\n\n\ndef _filter_by_include_exclude(filenames, include, exclude):\n    include_re, exclude_re = re.compile(include), re.compile(exclude)\n    return {\n        filename for filename in filenames\n        if (\n            include_re.search(filename) and\n            not exclude_re.search(filename) and\n            os.path.lexists(filename)\n        )\n    }\n\n\ndef _filter_by_types(filenames, types, exclude_types):\n    types, exclude_types = frozenset(types), frozenset(exclude_types)\n    ret = []\n    for filename in filenames:\n        tags = tags_from_path(filename)\n        if tags >= types and not tags & exclude_types:\n            ret.append(filename)\n    return tuple(ret)\n\n\nSKIPPED = 'Skipped'\nNO_FILES = '(no files to check)'\n\n\ndef _run_single_hook(filenames, hook, repo, args, skips, cols):\n    include, exclude = hook['files'], hook['exclude']\n    filenames = _filter_by_include_exclude(filenames, include, exclude)\n    types, exclude_types = hook['types'], hook['exclude_types']\n    filenames = _filter_by_types(filenames, types, exclude_types)\n\n    if hook['language'] == 'pcre':\n        logger.warning(\n            '`{}` (from {}) uses the deprecated pcre language.\\n'\n            'The pcre language is scheduled for removal in pre-commit 2.x.\\n'\n            'The pygrep language is a more portable (and usually drop-in) '\n            'replacement.'.format(hook['id'], repo.repo_config['repo']),\n        )\n\n    if hook['id'] in skips:\n        output.write(get_hook_message(\n            _hook_msg_start(hook, args.verbose),\n            end_msg=SKIPPED,\n            end_color=color.YELLOW,\n            use_color=args.color,\n            cols=cols,\n        ))\n        return 0\n    elif not filenames and not hook['always_run']:\n        output.write(get_hook_message(\n            _hook_msg_start(hook, args.verbose),\n            postfix=NO_FILES,\n            end_msg=SKIPPED,\n            end_color=color.TURQUOISE,\n            use_color=args.color,\n            cols=cols,\n        ))\n        return 0\n\n    # Print the hook and the dots first in case the hook takes hella long to\n    # run.\n    output.write(get_hook_message(\n        _hook_msg_start(hook, args.verbose), end_len=6, cols=cols,\n    ))\n    sys.stdout.flush()\n\n    diff_before = cmd_output(\n        'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,\n    )\n    retcode, stdout, stderr = repo.run_hook(\n        hook, tuple(filenames) if hook['pass_filenames'] else (),\n    )\n    diff_after = cmd_output(\n        'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,\n    )\n\n    file_modifications = diff_before != diff_after\n\n    # If the hook makes changes, fail the commit\n    if file_modifications:\n        retcode = 1\n\n    if retcode:\n        retcode = 1\n        print_color = color.RED\n        pass_fail = 'Failed'\n    else:\n        retcode = 0\n        print_color = color.GREEN\n        pass_fail = 'Passed'\n\n    output.write_line(color.format_color(pass_fail, print_color, args.color))\n\n    if (stdout or stderr or file_modifications) and (retcode or args.verbose):\n        output.write_line('hookid: {}\\n'.format(hook['id']))\n\n        # Print a message if failing due to file modifications\n        if file_modifications:\n            output.write('Files were modified by this hook.')\n\n            if stdout or stderr:\n                output.write_line(' Additional output:')\n\n            output.write_line()\n\n        for out in (stdout, stderr):\n            assert type(out) is bytes, type(out)\n            if out.strip():\n                output.write_line(out.strip(), logfile_name=hook['log_file'])\n        output.write_line()\n\n    return retcode\n\n\ndef _compute_cols(hooks, verbose):\n    \"\"\"Compute the number of columns to display hook messages.  The widest\n    that will be displayed is in the no files skipped case:\n\n        Hook name...(no files to check) Skipped\n\n    or in the verbose case\n\n        Hook name [hookid]...(no files to check) Skipped\n    \"\"\"\n    if hooks:\n        name_len = max(len(_hook_msg_start(hook, verbose)) for hook in hooks)\n    else:\n        name_len = 0\n\n    cols = name_len + 3 + len(NO_FILES) + 1 + len(SKIPPED)\n    return max(cols, 80)\n\n\ndef _all_filenames(args):\n    if args.origin and args.source:\n        return git.get_changed_files(args.origin, args.source)\n    elif args.hook_stage == 'commit-msg':\n        return (args.commit_msg_filename,)\n    elif args.files:\n        return args.files\n    elif args.all_files:\n        return git.get_all_files()\n    elif git.is_in_merge_conflict():\n        return git.get_conflicted_files()\n    else:\n        return git.get_staged_files()\n\n\ndef _run_hooks(config, repo_hooks, args, environ):\n    \"\"\"Actually run the hooks.\"\"\"\n    skips = _get_skips(environ)\n    cols = _compute_cols([hook for _, hook in repo_hooks], args.verbose)\n    filenames = _all_filenames(args)\n    filenames = _filter_by_include_exclude(filenames, '', config['exclude'])\n    retval = 0\n    for repo, hook in repo_hooks:\n        retval |= _run_single_hook(filenames, hook, repo, args, skips, cols)\n        if retval and config['fail_fast']:\n            break\n    if (\n            retval and\n            args.show_diff_on_failure and\n            subprocess.call(('git', 'diff', '--quiet', '--no-ext-diff')) != 0\n    ):\n        print('All changes made by hooks:')\n        subprocess.call(('git', '--no-pager', 'diff', '--no-ext-diff'))\n    return retval\n\n\ndef _has_unmerged_paths():\n    _, stdout, _ = cmd_output('git', 'ls-files', '--unmerged')\n    return bool(stdout.strip())\n\n\ndef _has_unstaged_config(runner):\n    retcode, _, _ = cmd_output(\n        'git', 'diff', '--no-ext-diff', '--exit-code', runner.config_file_path,\n        retcode=None,\n    )\n    # be explicit, other git errors don't mean it has an unstaged config.\n    return retcode == 1\n\n\ndef run(runner, args, environ=os.environ):\n    no_stash = args.all_files or bool(args.files)\n\n    # Check if we have unresolved merge conflict files and fail fast.\n    if _has_unmerged_paths():\n        logger.error('Unmerged files.  Resolve before committing.')\n        return 1\n    if bool(args.source) != bool(args.origin):\n        logger.error('Specify both --origin and --source.')\n        return 1\n    if _has_unstaged_config(runner) and not no_stash:\n        logger.error(\n            'Your pre-commit configuration is unstaged.\\n'\n            '`git add {}` to fix this.'.format(runner.config_file),\n        )\n        return 1\n\n    # Expose origin / source as environment variables for hooks to consume\n    if args.origin and args.source:\n        environ['PRE_COMMIT_ORIGIN'] = args.origin\n        environ['PRE_COMMIT_SOURCE'] = args.source\n\n    if no_stash:\n        ctx = noop_context()\n    else:\n        ctx = staged_files_only(runner.store.directory)\n\n    with ctx:\n        repo_hooks = []\n        for repo in runner.repositories:\n            for _, hook in repo.hooks:\n                if (\n                    (not args.hook or hook['id'] == args.hook) and\n                    not hook['stages'] or args.hook_stage in hook['stages']\n                ):\n                    repo_hooks.append((repo, hook))\n\n        if args.hook and not repo_hooks:\n            output.write_line('No hook with id `{}`'.format(args.hook))\n            return 1\n\n        for repo in {repo for repo, _ in repo_hooks}:\n            repo.require_installed()\n\n        return _run_hooks(runner.config, repo_hooks, args, environ)\n", "path": "pre_commit/commands/run.py"}]}