We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Not working from SmartGit
I know that this issue may not be caused by `pre-commit` directly, but figured out you guys could help me. Trying to commit directly from `SmartGit` prints this:

```
~/Development/ProjectName> git add --force -- Libraries/IOUtilities/NSString+IOUtilities.m
~/Development/ProjectName> git commit --file=/var/folders/yj/l8y5kytd4tggcv7grrnpznh80000gn/T/smartgit-2497340677383657620tmp/commit-4165014595931887528.tmp -o -- Libraries/IOUtilities/NSString+IOUtilities.m
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
An unexpected error has occurred: CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory
    
Check the log at /Users/revolt/.cache/pre-commit/pre-commit.log
```

and `cat /Users/revolt/.cache/pre-commit/pre-commit.log`:

```
An unexpected error has occurred: CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory
    

Traceback (most recent call last):
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/error_handler.py", line 47, in error_handler
    yield
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/main.py", line 259, in main
    return run(runner, args)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/commands/run.py", line 244, in run
    for _, hook in repo.hooks:
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py", line 173, in hooks
    if hook['id'] not in self.manifest_hooks:
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py", line 167, in manifest_hooks
    manifest_path = os.path.join(self._repo_path, C.MANIFEST_FILE)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py", line 155, in _repo_path
    self.repo_config['repo'], self.repo_config['sha'],
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py", line 154, in clone
    return self._new_repo(repo, ref, clone_strategy)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py", line 130, in _new_repo
    make_strategy(directory)
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py", line 151, in clone_strategy
    env=no_git_env(),
  File "/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/util.py", line 187, in cmd_output
    returncode, cmd, retcode, output=(stdout, stderr),
pre_commit.util.CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')
Return code: 1
Expected return code: 0
Output: (none)
Errors: 
    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory
```


--- 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/git.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import logging
4 import os.path
5 import sys
6 
7 from pre_commit.util import cmd_output
8 
9 
10 logger = logging.getLogger(__name__)
11 
12 
13 def zsplit(s):
14     s = s.strip('\0')
15     if s:
16         return s.split('\0')
17     else:
18         return []
19 
20 
21 def no_git_env():
22     # Too many bugs dealing with environment variables and GIT:
23     # https://github.com/pre-commit/pre-commit/issues/300
24     # In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running
25     # pre-commit hooks
26     # In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE
27     # while running pre-commit hooks in submodules.
28     # GIT_DIR: Causes git clone to clone wrong thing
29     # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit
30     return {
31         k: v for k, v in os.environ.items()
32         if not k.startswith('GIT_') or k in {'GIT_SSH', 'GIT_SSH_COMMAND'}
33     }
34 
35 
36 def get_root():
37     return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()
38 
39 
40 def get_git_dir(git_root='.'):
41     opts = ('--git-common-dir', '--git-dir')
42     _, out, _ = cmd_output('git', 'rev-parse', *opts, cwd=git_root)
43     for line, opt in zip(out.splitlines(), opts):
44         if line != opt:  # pragma: no branch (git < 2.5)
45             return os.path.normpath(os.path.join(git_root, line))
46     else:
47         raise AssertionError('unreachable: no git dir')
48 
49 
50 def get_remote_url(git_root):
51     ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]
52     return ret.strip()
53 
54 
55 def is_in_merge_conflict():
56     git_dir = get_git_dir('.')
57     return (
58         os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and
59         os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))
60     )
61 
62 
63 def parse_merge_msg_for_conflicts(merge_msg):
64     # Conflicted files start with tabs
65     return [
66         line.lstrip(b'#').strip().decode('UTF-8')
67         for line in merge_msg.splitlines()
68         # '#\t' for git 2.4.1
69         if line.startswith((b'\t', b'#\t'))
70     ]
71 
72 
73 def get_conflicted_files():
74     logger.info('Checking merge-conflict files only.')
75     # Need to get the conflicted files from the MERGE_MSG because they could
76     # have resolved the conflict by choosing one side or the other
77     with open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb') as f:
78         merge_msg = f.read()
79     merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)
80 
81     # This will get the rest of the changes made after the merge.
82     # If they resolved the merge conflict by choosing a mesh of both sides
83     # this will also include the conflicted files
84     tree_hash = cmd_output('git', 'write-tree')[1].strip()
85     merge_diff_filenames = zsplit(cmd_output(
86         'git', 'diff', '--name-only', '--no-ext-diff', '-z',
87         '-m', tree_hash, 'HEAD', 'MERGE_HEAD',
88     )[1])
89     return set(merge_conflict_filenames) | set(merge_diff_filenames)
90 
91 
92 def get_staged_files():
93     return zsplit(cmd_output(
94         'git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z',
95         # Everything except for D
96         '--diff-filter=ACMRTUXB',
97     )[1])
98 
99 
100 def intent_to_add_files():
101     _, stdout_binary, _ = cmd_output('git', 'status', '--porcelain', '-z')
102     parts = list(reversed(zsplit(stdout_binary)))
103     intent_to_add = []
104     while parts:
105         line = parts.pop()
106         status, filename = line[:3], line[3:]
107         if status[0] in {'C', 'R'}:  # renames / moves have an additional arg
108             parts.pop()
109         if status[1] == 'A':
110             intent_to_add.append(filename)
111     return intent_to_add
112 
113 
114 def get_all_files():
115     return zsplit(cmd_output('git', 'ls-files', '-z')[1])
116 
117 
118 def get_changed_files(new, old):
119     return zsplit(cmd_output(
120         'git', 'diff', '--name-only', '--no-ext-diff', '-z',
121         '{}...{}'.format(old, new),
122     )[1])
123 
124 
125 def head_rev(remote):
126     _, out, _ = cmd_output('git', 'ls-remote', '--exit-code', remote, 'HEAD')
127     return out.split()[0]
128 
129 
130 def has_diff(*args, **kwargs):
131     repo = kwargs.pop('repo', '.')
132     assert not kwargs, kwargs
133     cmd = ('git', 'diff', '--quiet', '--no-ext-diff') + args
134     return cmd_output(*cmd, cwd=repo, retcode=None)[0]
135 
136 
137 def commit(repo='.'):
138     env = no_git_env()
139     name, email = 'pre-commit', 'asottile+pre-commit@umich.edu'
140     env['GIT_AUTHOR_NAME'] = env['GIT_COMMITTER_NAME'] = name
141     env['GIT_AUTHOR_EMAIL'] = env['GIT_COMMITTER_EMAIL'] = email
142     cmd = ('git', 'commit', '--no-edit', '--no-gpg-sign', '-n', '-minit')
143     cmd_output(*cmd, cwd=repo, env=env)
144 
145 
146 def git_path(name, repo='.'):
147     _, out, _ = cmd_output('git', 'rev-parse', '--git-path', name, cwd=repo)
148     return os.path.join(repo, out.strip())
149 
150 
151 def check_for_cygwin_mismatch():
152     """See https://github.com/pre-commit/pre-commit/issues/354"""
153     if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)
154         is_cygwin_python = sys.platform == 'cygwin'
155         toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]
156         is_cygwin_git = toplevel.startswith('/')
157 
158         if is_cygwin_python ^ is_cygwin_git:
159             exe_type = {True: '(cygwin)', False: '(windows)'}
160             logger.warn(
161                 'pre-commit has detected a mix of cygwin python / git\n'
162                 'This combination is not supported, it is likely you will '
163                 'receive an error later in the program.\n'
164                 'Make sure to use cygwin git+python while using cygwin\n'
165                 'These can be installed through the cygwin installer.\n'
166                 ' - python {}\n'
167                 ' - git {}\n'.format(
168                     exe_type[is_cygwin_python], exe_type[is_cygwin_git],
169                 ),
170             )
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/git.py b/pre_commit/git.py
--- a/pre_commit/git.py
+++ b/pre_commit/git.py
@@ -29,7 +29,8 @@
     # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit
     return {
         k: v for k, v in os.environ.items()
-        if not k.startswith('GIT_') or k in {'GIT_SSH', 'GIT_SSH_COMMAND'}
+        if not k.startswith('GIT_') or
+        k in {'GIT_EXEC_PATH', 'GIT_SSH', 'GIT_SSH_COMMAND'}
     }

{"golden_diff": "diff --git a/pre_commit/git.py b/pre_commit/git.py\n--- a/pre_commit/git.py\n+++ b/pre_commit/git.py\n@@ -29,7 +29,8 @@\n     # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit\n     return {\n         k: v for k, v in os.environ.items()\n-        if not k.startswith('GIT_') or k in {'GIT_SSH', 'GIT_SSH_COMMAND'}\n+        if not k.startswith('GIT_') or\n+        k in {'GIT_EXEC_PATH', 'GIT_SSH', 'GIT_SSH_COMMAND'}\n     }\n", "issue": "Not working from SmartGit\nI know that this issue may not be caused by `pre-commit` directly, but figured out you guys could help me. Trying to commit directly from `SmartGit` prints this:\r\n\r\n```\r\n~/Development/ProjectName> git add --force -- Libraries/IOUtilities/NSString+IOUtilities.m\r\n~/Development/ProjectName> git commit --file=/var/folders/yj/l8y5kytd4tggcv7grrnpznh80000gn/T/smartgit-2497340677383657620tmp/commit-4165014595931887528.tmp -o -- Libraries/IOUtilities/NSString+IOUtilities.m\r\n[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.\r\nAn unexpected error has occurred: CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')\r\nReturn code: 1\r\nExpected return code: 0\r\nOutput: (none)\r\nErrors: \r\n    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory\r\n    \r\nCheck the log at /Users/revolt/.cache/pre-commit/pre-commit.log\r\n```\r\n\r\nand `cat /Users/revolt/.cache/pre-commit/pre-commit.log`:\r\n\r\n```\r\nAn unexpected error has occurred: CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')\r\nReturn code: 1\r\nExpected return code: 0\r\nOutput: (none)\r\nErrors: \r\n    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory\r\n    \r\n\r\nTraceback (most recent call last):\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/error_handler.py\", line 47, in error_handler\r\n    yield\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/main.py\", line 259, in main\r\n    return run(runner, args)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/commands/run.py\", line 244, in run\r\n    for _, hook in repo.hooks:\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py\", line 26, in __get__\r\n    value = obj.__dict__[self.func.__name__] = self.func(obj)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py\", line 173, in hooks\r\n    if hook['id'] not in self.manifest_hooks:\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py\", line 26, in __get__\r\n    value = obj.__dict__[self.func.__name__] = self.func(obj)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py\", line 167, in manifest_hooks\r\n    manifest_path = os.path.join(self._repo_path, C.MANIFEST_FILE)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/cached_property.py\", line 26, in __get__\r\n    value = obj.__dict__[self.func.__name__] = self.func(obj)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/repository.py\", line 155, in _repo_path\r\n    self.repo_config['repo'], self.repo_config['sha'],\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py\", line 154, in clone\r\n    return self._new_repo(repo, ref, clone_strategy)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py\", line 130, in _new_repo\r\n    make_strategy(directory)\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/store.py\", line 151, in clone_strategy\r\n    env=no_git_env(),\r\n  File \"/usr/local/Cellar/pre-commit/1.4.1/libexec/lib/python3.6/site-packages/pre_commit/util.py\", line 187, in cmd_output\r\n    returncode, cmd, retcode, output=(stdout, stderr),\r\npre_commit.util.CalledProcessError: Command: ('/Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git', 'submodule', 'update', '--init', '--recursive')\r\nReturn code: 1\r\nExpected return code: 0\r\nOutput: (none)\r\nErrors: \r\n    /Applications/SmartGit.app/Contents/Resources/git/libexec/git-core/git-sh-setup: line 46: /usr/local/git/libexec/git-core/git-sh-i18n: No such file or directory\r\n```\r\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport logging\nimport os.path\nimport sys\n\nfrom pre_commit.util import cmd_output\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef zsplit(s):\n    s = s.strip('\\0')\n    if s:\n        return s.split('\\0')\n    else:\n        return []\n\n\ndef no_git_env():\n    # Too many bugs dealing with environment variables and GIT:\n    # https://github.com/pre-commit/pre-commit/issues/300\n    # In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running\n    # pre-commit hooks\n    # In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE\n    # while running pre-commit hooks in submodules.\n    # GIT_DIR: Causes git clone to clone wrong thing\n    # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit\n    return {\n        k: v for k, v in os.environ.items()\n        if not k.startswith('GIT_') or k in {'GIT_SSH', 'GIT_SSH_COMMAND'}\n    }\n\n\ndef get_root():\n    return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()\n\n\ndef get_git_dir(git_root='.'):\n    opts = ('--git-common-dir', '--git-dir')\n    _, out, _ = cmd_output('git', 'rev-parse', *opts, cwd=git_root)\n    for line, opt in zip(out.splitlines(), opts):\n        if line != opt:  # pragma: no branch (git < 2.5)\n            return os.path.normpath(os.path.join(git_root, line))\n    else:\n        raise AssertionError('unreachable: no git dir')\n\n\ndef get_remote_url(git_root):\n    ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]\n    return ret.strip()\n\n\ndef is_in_merge_conflict():\n    git_dir = get_git_dir('.')\n    return (\n        os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and\n        os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))\n    )\n\n\ndef parse_merge_msg_for_conflicts(merge_msg):\n    # Conflicted files start with tabs\n    return [\n        line.lstrip(b'#').strip().decode('UTF-8')\n        for line in merge_msg.splitlines()\n        # '#\\t' for git 2.4.1\n        if line.startswith((b'\\t', b'#\\t'))\n    ]\n\n\ndef get_conflicted_files():\n    logger.info('Checking merge-conflict files only.')\n    # Need to get the conflicted files from the MERGE_MSG because they could\n    # have resolved the conflict by choosing one side or the other\n    with open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb') as f:\n        merge_msg = f.read()\n    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\n\n    # This will get the rest of the changes made after the merge.\n    # If they resolved the merge conflict by choosing a mesh of both sides\n    # this will also include the conflicted files\n    tree_hash = cmd_output('git', 'write-tree')[1].strip()\n    merge_diff_filenames = zsplit(cmd_output(\n        'git', 'diff', '--name-only', '--no-ext-diff', '-z',\n        '-m', tree_hash, 'HEAD', 'MERGE_HEAD',\n    )[1])\n    return set(merge_conflict_filenames) | set(merge_diff_filenames)\n\n\ndef get_staged_files():\n    return zsplit(cmd_output(\n        'git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z',\n        # Everything except for D\n        '--diff-filter=ACMRTUXB',\n    )[1])\n\n\ndef intent_to_add_files():\n    _, stdout_binary, _ = cmd_output('git', 'status', '--porcelain', '-z')\n    parts = list(reversed(zsplit(stdout_binary)))\n    intent_to_add = []\n    while parts:\n        line = parts.pop()\n        status, filename = line[:3], line[3:]\n        if status[0] in {'C', 'R'}:  # renames / moves have an additional arg\n            parts.pop()\n        if status[1] == 'A':\n            intent_to_add.append(filename)\n    return intent_to_add\n\n\ndef get_all_files():\n    return zsplit(cmd_output('git', 'ls-files', '-z')[1])\n\n\ndef get_changed_files(new, old):\n    return zsplit(cmd_output(\n        'git', 'diff', '--name-only', '--no-ext-diff', '-z',\n        '{}...{}'.format(old, new),\n    )[1])\n\n\ndef head_rev(remote):\n    _, out, _ = cmd_output('git', 'ls-remote', '--exit-code', remote, 'HEAD')\n    return out.split()[0]\n\n\ndef has_diff(*args, **kwargs):\n    repo = kwargs.pop('repo', '.')\n    assert not kwargs, kwargs\n    cmd = ('git', 'diff', '--quiet', '--no-ext-diff') + args\n    return cmd_output(*cmd, cwd=repo, retcode=None)[0]\n\n\ndef commit(repo='.'):\n    env = no_git_env()\n    name, email = 'pre-commit', 'asottile+pre-commit@umich.edu'\n    env['GIT_AUTHOR_NAME'] = env['GIT_COMMITTER_NAME'] = name\n    env['GIT_AUTHOR_EMAIL'] = env['GIT_COMMITTER_EMAIL'] = email\n    cmd = ('git', 'commit', '--no-edit', '--no-gpg-sign', '-n', '-minit')\n    cmd_output(*cmd, cwd=repo, env=env)\n\n\ndef git_path(name, repo='.'):\n    _, out, _ = cmd_output('git', 'rev-parse', '--git-path', name, cwd=repo)\n    return os.path.join(repo, out.strip())\n\n\ndef check_for_cygwin_mismatch():\n    \"\"\"See https://github.com/pre-commit/pre-commit/issues/354\"\"\"\n    if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)\n        is_cygwin_python = sys.platform == 'cygwin'\n        toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]\n        is_cygwin_git = toplevel.startswith('/')\n\n        if is_cygwin_python ^ is_cygwin_git:\n            exe_type = {True: '(cygwin)', False: '(windows)'}\n            logger.warn(\n                'pre-commit has detected a mix of cygwin python / git\\n'\n                'This combination is not supported, it is likely you will '\n                'receive an error later in the program.\\n'\n                'Make sure to use cygwin git+python while using cygwin\\n'\n                'These can be installed through the cygwin installer.\\n'\n                ' - python {}\\n'\n                ' - git {}\\n'.format(\n                    exe_type[is_cygwin_python], exe_type[is_cygwin_git],\n                ),\n            )\n", "path": "pre_commit/git.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport logging\nimport os.path\nimport sys\n\nfrom pre_commit.util import cmd_output\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef zsplit(s):\n    s = s.strip('\\0')\n    if s:\n        return s.split('\\0')\n    else:\n        return []\n\n\ndef no_git_env():\n    # Too many bugs dealing with environment variables and GIT:\n    # https://github.com/pre-commit/pre-commit/issues/300\n    # In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running\n    # pre-commit hooks\n    # In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE\n    # while running pre-commit hooks in submodules.\n    # GIT_DIR: Causes git clone to clone wrong thing\n    # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit\n    return {\n        k: v for k, v in os.environ.items()\n        if not k.startswith('GIT_') or\n        k in {'GIT_EXEC_PATH', 'GIT_SSH', 'GIT_SSH_COMMAND'}\n    }\n\n\ndef get_root():\n    return cmd_output('git', 'rev-parse', '--show-toplevel')[1].strip()\n\n\ndef get_git_dir(git_root='.'):\n    opts = ('--git-common-dir', '--git-dir')\n    _, out, _ = cmd_output('git', 'rev-parse', *opts, cwd=git_root)\n    for line, opt in zip(out.splitlines(), opts):\n        if line != opt:  # pragma: no branch (git < 2.5)\n            return os.path.normpath(os.path.join(git_root, line))\n    else:\n        raise AssertionError('unreachable: no git dir')\n\n\ndef get_remote_url(git_root):\n    ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]\n    return ret.strip()\n\n\ndef is_in_merge_conflict():\n    git_dir = get_git_dir('.')\n    return (\n        os.path.exists(os.path.join(git_dir, 'MERGE_MSG')) and\n        os.path.exists(os.path.join(git_dir, 'MERGE_HEAD'))\n    )\n\n\ndef parse_merge_msg_for_conflicts(merge_msg):\n    # Conflicted files start with tabs\n    return [\n        line.lstrip(b'#').strip().decode('UTF-8')\n        for line in merge_msg.splitlines()\n        # '#\\t' for git 2.4.1\n        if line.startswith((b'\\t', b'#\\t'))\n    ]\n\n\ndef get_conflicted_files():\n    logger.info('Checking merge-conflict files only.')\n    # Need to get the conflicted files from the MERGE_MSG because they could\n    # have resolved the conflict by choosing one side or the other\n    with open(os.path.join(get_git_dir('.'), 'MERGE_MSG'), 'rb') as f:\n        merge_msg = f.read()\n    merge_conflict_filenames = parse_merge_msg_for_conflicts(merge_msg)\n\n    # This will get the rest of the changes made after the merge.\n    # If they resolved the merge conflict by choosing a mesh of both sides\n    # this will also include the conflicted files\n    tree_hash = cmd_output('git', 'write-tree')[1].strip()\n    merge_diff_filenames = zsplit(cmd_output(\n        'git', 'diff', '--name-only', '--no-ext-diff', '-z',\n        '-m', tree_hash, 'HEAD', 'MERGE_HEAD',\n    )[1])\n    return set(merge_conflict_filenames) | set(merge_diff_filenames)\n\n\ndef get_staged_files():\n    return zsplit(cmd_output(\n        'git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z',\n        # Everything except for D\n        '--diff-filter=ACMRTUXB',\n    )[1])\n\n\ndef intent_to_add_files():\n    _, stdout_binary, _ = cmd_output('git', 'status', '--porcelain', '-z')\n    parts = list(reversed(zsplit(stdout_binary)))\n    intent_to_add = []\n    while parts:\n        line = parts.pop()\n        status, filename = line[:3], line[3:]\n        if status[0] in {'C', 'R'}:  # renames / moves have an additional arg\n            parts.pop()\n        if status[1] == 'A':\n            intent_to_add.append(filename)\n    return intent_to_add\n\n\ndef get_all_files():\n    return zsplit(cmd_output('git', 'ls-files', '-z')[1])\n\n\ndef get_changed_files(new, old):\n    return zsplit(cmd_output(\n        'git', 'diff', '--name-only', '--no-ext-diff', '-z',\n        '{}...{}'.format(old, new),\n    )[1])\n\n\ndef head_rev(remote):\n    _, out, _ = cmd_output('git', 'ls-remote', '--exit-code', remote, 'HEAD')\n    return out.split()[0]\n\n\ndef has_diff(*args, **kwargs):\n    repo = kwargs.pop('repo', '.')\n    assert not kwargs, kwargs\n    cmd = ('git', 'diff', '--quiet', '--no-ext-diff') + args\n    return cmd_output(*cmd, cwd=repo, retcode=None)[0]\n\n\ndef commit(repo='.'):\n    env = no_git_env()\n    name, email = 'pre-commit', 'asottile+pre-commit@umich.edu'\n    env['GIT_AUTHOR_NAME'] = env['GIT_COMMITTER_NAME'] = name\n    env['GIT_AUTHOR_EMAIL'] = env['GIT_COMMITTER_EMAIL'] = email\n    cmd = ('git', 'commit', '--no-edit', '--no-gpg-sign', '-n', '-minit')\n    cmd_output(*cmd, cwd=repo, env=env)\n\n\ndef git_path(name, repo='.'):\n    _, out, _ = cmd_output('git', 'rev-parse', '--git-path', name, cwd=repo)\n    return os.path.join(repo, out.strip())\n\n\ndef check_for_cygwin_mismatch():\n    \"\"\"See https://github.com/pre-commit/pre-commit/issues/354\"\"\"\n    if sys.platform in ('cygwin', 'win32'):  # pragma: no cover (windows)\n        is_cygwin_python = sys.platform == 'cygwin'\n        toplevel = cmd_output('git', 'rev-parse', '--show-toplevel')[1]\n        is_cygwin_git = toplevel.startswith('/')\n\n        if is_cygwin_python ^ is_cygwin_git:\n            exe_type = {True: '(cygwin)', False: '(windows)'}\n            logger.warn(\n                'pre-commit has detected a mix of cygwin python / git\\n'\n                'This combination is not supported, it is likely you will '\n                'receive an error later in the program.\\n'\n                'Make sure to use cygwin git+python while using cygwin\\n'\n                'These can be installed through the cygwin installer.\\n'\n                ' - python {}\\n'\n                ' - git {}\\n'.format(\n                    exe_type[is_cygwin_python], exe_type[is_cygwin_git],\n                ),\n            )\n", "path": "pre_commit/git.py"}]}